From python-checkins at python.org Sun Apr 1 20:24:24 2007 From: python-checkins at python.org (neal.norwitz) Date: Sun, 1 Apr 2007 20:24:24 +0200 (CEST) Subject: [Python-checkins] r54644 - in python/trunk: Lib/distutils/msvccompiler.py Misc/NEWS Message-ID: <20070401182424.4FB111E4006@bag.python.org> Author: neal.norwitz Date: Sun Apr 1 20:24:22 2007 New Revision: 54644 Modified: python/trunk/Lib/distutils/msvccompiler.py python/trunk/Misc/NEWS Log: SF #1685563, MSVCCompiler creates redundant and long PATH strings If MSVCCompiler.initialize() was called multiple times, the path would get duplicated. On Windows, this is a problem because the path is limited to 4k. There's no benefit in adding a path multiple times, so prevent that from occuring. We also normalize the path before checking for duplicates so things like /a and /a/ won't both be stored. Will backport. Modified: python/trunk/Lib/distutils/msvccompiler.py ============================================================================== --- python/trunk/Lib/distutils/msvccompiler.py (original) +++ python/trunk/Lib/distutils/msvccompiler.py Sun Apr 1 20:24:22 2007 @@ -187,6 +187,19 @@ j = string.find(sys.version, ")", i) return sys.version[i+len(prefix):j] +def normalize_and_reduce_paths(paths): + """Return a list of normalized paths with duplicates removed. + + The current order of paths is maintained. + """ + # Paths are normalized so things like: /a and /a/ aren't both preserved. + reduced_paths = [] + for p in paths: + np = os.path.normpath(p) + # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. + if np not in reduced_paths: + reduced_paths.append(np) + return reduced_paths class MSVCCompiler (CCompiler) : @@ -270,6 +283,7 @@ self.__paths.append(p) except KeyError: pass + self.__paths = normalize_and_reduce_paths(self.__paths) os.environ['path'] = string.join(self.__paths, ';') self.preprocess_options = None Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sun Apr 1 20:24:22 2007 @@ -1,4 +1,4 @@ -__init+++++++++++ ++++++++++++ Python News +++++++++++ @@ -200,6 +200,8 @@ Library ------- +- Patch #1685563: remove (don't add) duplicate paths in distutils.MSVCCompiler. + - Added a timeout parameter to the constructor of other protocols (telnetlib, ftplib, smtplib and poplib). This is second part of the work started with create_connection() and timeout in httplib, and From python-checkins at python.org Sun Apr 1 20:29:53 2007 From: python-checkins at python.org (neal.norwitz) Date: Sun, 1 Apr 2007 20:29:53 +0200 (CEST) Subject: [Python-checkins] r54645 - in python/branches/release25-maint: Lib/distutils/msvccompiler.py Misc/NEWS Message-ID: <20070401182953.D922F1E4006@bag.python.org> Author: neal.norwitz Date: Sun Apr 1 20:29:47 2007 New Revision: 54645 Modified: python/branches/release25-maint/Lib/distutils/msvccompiler.py python/branches/release25-maint/Misc/NEWS Log: Backport 54644: SF #1685563, MSVCCompiler creates redundant and long PATH strings If MSVCCompiler.initialize() was called multiple times, the path would get duplicated. On Windows, this is a problem because the path is limited to 4k. There's no benefit in adding a path multiple times, so prevent that from occuring. We also normalize the path before checking for duplicates so things like /a and /a/ won't both be stored. Modified: python/branches/release25-maint/Lib/distutils/msvccompiler.py ============================================================================== --- python/branches/release25-maint/Lib/distutils/msvccompiler.py (original) +++ python/branches/release25-maint/Lib/distutils/msvccompiler.py Sun Apr 1 20:29:47 2007 @@ -187,6 +187,19 @@ j = string.find(sys.version, ")", i) return sys.version[i+len(prefix):j] +def normalize_and_reduce_paths(paths): + """Return a list of normalized paths with duplicates removed. + + The current order of paths is maintained. + """ + # Paths are normalized so things like: /a and /a/ aren't both preserved. + reduced_paths = [] + for p in paths: + np = os.path.normpath(p) + # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. + if np not in reduced_paths: + reduced_paths.append(np) + return reduced_paths class MSVCCompiler (CCompiler) : @@ -270,6 +283,7 @@ self.__paths.append(p) except KeyError: pass + self.__paths = normalize_and_reduce_paths(self.__paths) os.environ['path'] = string.join(self.__paths, ';') self.preprocess_options = None Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Sun Apr 1 20:29:47 2007 @@ -219,6 +219,8 @@ Library ------- +- Patch #1685563: remove (don't add) duplicate paths in distutils.MSVCCompiler. + - Bug #978833: Revert r50844, as it broke _socketobject.dup. - Bug #1675967: re patterns pickled with Python 2.4 and earlier can From python-checkins at python.org Sun Apr 1 20:47:33 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 1 Apr 2007 20:47:33 +0200 (CEST) Subject: [Python-checkins] r54646 - in python/trunk: Lib/_strptime.py Lib/test/test_strptime.py Misc/NEWS Message-ID: <20070401184733.D18E21E400B@bag.python.org> Author: brett.cannon Date: Sun Apr 1 20:47:27 2007 New Revision: 54646 Modified: python/trunk/Lib/_strptime.py python/trunk/Lib/test/test_strptime.py python/trunk/Misc/NEWS Log: time.strptime's caching of its locale object was being recreated when the locale changed but not used during the function call it was recreated during. The test in this checkin is untested (OS X does not have the proper locale support for me to test), although the fix for the bug this deals with was tested by the OP (#1290505). Once the buildbots verify the test at least doesn't fail it becomes a backport candidate. Modified: python/trunk/Lib/_strptime.py ============================================================================== --- python/trunk/Lib/_strptime.py (original) +++ python/trunk/Lib/_strptime.py Sun Apr 1 20:47:27 2007 @@ -295,17 +295,16 @@ """Return a time struct based on the input string and the format string.""" global _TimeRE_cache, _regex_cache with _cache_lock: - time_re = _TimeRE_cache - locale_time = time_re.locale_time - if _getlang() != locale_time.lang: + if _getlang() != _TimeRE_cache.locale_time.lang: _TimeRE_cache = TimeRE() - _regex_cache = {} + _regex_cache.clear() if len(_regex_cache) > _CACHE_MAX_SIZE: _regex_cache.clear() + locale_time = _TimeRE_cache.locale_time format_regex = _regex_cache.get(format) if not format_regex: try: - format_regex = time_re.compile(format) + format_regex = _TimeRE_cache.compile(format) # KeyError raised when a bad format is found; can be specified as # \\, in which case it was a stray % but with a space after it except KeyError, err: Modified: python/trunk/Lib/test/test_strptime.py ============================================================================== --- python/trunk/Lib/test/test_strptime.py (original) +++ python/trunk/Lib/test/test_strptime.py Sun Apr 1 20:47:27 2007 @@ -505,6 +505,23 @@ self.failIfEqual(locale_time_id, id(_strptime._TimeRE_cache.locale_time)) + def test_TimeRE_recreation(self): + # The TimeRE instance should be recreated upon changing the locale. + locale_info = locale.getlocale(locale.LC_TIME) + try: + locale.setlocale(locale.LC_TIME, ('en_US', 'UTF8')) + except locale.Error: + return + try: + _strptime.strptime('10', '%d') + first_time_re_id = id(_strptime._TimeRE_cache) + locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8')) + _strptime.strptime('10', '%d') + second_time_re_id = id(_strptime._TimeRE_cache) + self.failIfEqual(first_time_re_id, second_time_re_id) + finally: + locale.setlocale(locale.LC_TIME, locale_info) + def test_main(): test_support.run_unittest( Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sun Apr 1 20:47:27 2007 @@ -200,6 +200,9 @@ Library ------- +- Bug #1290505: time.strptime's internal cache of locale information is now + properly recreated when the locale is changed. + - Patch #1685563: remove (don't add) duplicate paths in distutils.MSVCCompiler. - Added a timeout parameter to the constructor of other protocols From buildbot at python.org Sun Apr 1 21:25:31 2007 From: buildbot at python.org (buildbot at python.org) Date: Sun, 01 Apr 2007 19:25:31 +0000 Subject: [Python-checkins] buildbot warnings in x86 gentoo trunk Message-ID: <20070401192531.766EA1E4007@bag.python.org> The Buildbot has detected a new failure of x86 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520gentoo%2520trunk/builds/2102 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_strptime ====================================================================== ERROR: test_TimeRE_recreation (test.test_strptime.CacheTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_strptime.py", line 518, in test_TimeRE_recreation locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8')) File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/locale.py", line 476, in setlocale return _setlocale(category, locale) Error: unsupported locale setting make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sun Apr 1 21:26:22 2007 From: buildbot at python.org (buildbot at python.org) Date: Sun, 01 Apr 2007 19:26:22 +0000 Subject: [Python-checkins] buildbot warnings in amd64 gentoo trunk Message-ID: <20070401192622.6BF731E400B@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%2520gentoo%2520trunk/builds/1919 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_strptime ====================================================================== ERROR: test_TimeRE_recreation (test.test_strptime.CacheTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_strptime.py", line 518, in test_TimeRE_recreation locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8')) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/locale.py", line 476, in setlocale return _setlocale(category, locale) Error: unsupported locale setting make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sun Apr 1 21:29:23 2007 From: buildbot at python.org (buildbot at python.org) Date: Sun, 01 Apr 2007 19:29:23 +0000 Subject: [Python-checkins] buildbot warnings in alpha Tru64 5.1 2.5 Message-ID: <20070401192924.168C81E4016@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%25202.5/builds/232 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: neal.norwitz Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_socketserver Traceback (most recent call last): File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_socketserver.py", line 81, in run svr = svrcls(self.__addr, self.__hdlrcls) File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/SocketServer.py", line 330, in __init__ self.server_bind() File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/SocketServer.py", line 341, in server_bind self.socket.bind(self.server_address) File "", line 1, in bind error: (48, 'Address already in use') Traceback (most recent call last): File "./Lib/test/regrtest.py", line 557, in runtest_inner indirect_test() File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_socketserver.py", line 212, in test_main testall() File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_socketserver.py", line 197, in testall testloop(socket.AF_INET, udpservers, MyDatagramHandler, testdgram) File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_socketserver.py", line 144, in testloop testfunc(proto, addr) File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_socketserver.py", line 53, in testdgram buf = data = receive(s, 100) File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_socketserver.py", line 48, in receive raise RuntimeError, "timed out on %r" % (sock,) RuntimeError: timed out on sincerely, -The Buildbot From python-checkins at python.org Sun Apr 1 21:46:23 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 1 Apr 2007 21:46:23 +0200 (CEST) Subject: [Python-checkins] r54647 - python/trunk/Lib/test/test_strptime.py Message-ID: <20070401194623.0839A1E4007@bag.python.org> Author: brett.cannon Date: Sun Apr 1 21:46:19 2007 New Revision: 54647 Modified: python/trunk/Lib/test/test_strptime.py Log: Fix the test for recreating the locale cache object by not worrying about if one of the test locales cannot be set. Modified: python/trunk/Lib/test/test_strptime.py ============================================================================== --- python/trunk/Lib/test/test_strptime.py (original) +++ python/trunk/Lib/test/test_strptime.py Sun Apr 1 21:46:19 2007 @@ -514,11 +514,23 @@ return try: _strptime.strptime('10', '%d') + # Get id of current cache object. first_time_re_id = id(_strptime._TimeRE_cache) - locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8')) - _strptime.strptime('10', '%d') - second_time_re_id = id(_strptime._TimeRE_cache) - self.failIfEqual(first_time_re_id, second_time_re_id) + try: + # Change the locale and force a recreation of the cache. + locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8')) + _strptime.strptime('10', '%d') + # Get the new cache object's id. + second_time_re_id = id(_strptime._TimeRE_cache) + # They should not be equal. + self.failIfEqual(first_time_re_id, second_time_re_id) + # Possible test locale is not supported while initial locale is. + # If this is the case just suppress the exception and fall-through + # to the reseting to the original locale. + except locale.Error: + pass + # Make sure we don't trample on the locale setting once we leave the + # test. finally: locale.setlocale(locale.LC_TIME, locale_info) From buildbot at python.org Sun Apr 1 21:58:45 2007 From: buildbot at python.org (buildbot at python.org) Date: Sun, 01 Apr 2007 19:58:45 +0000 Subject: [Python-checkins] buildbot warnings in x86 W2k trunk Message-ID: <20070401195845.292271E4006@bag.python.org> The Buildbot has detected a new failure of x86 W2k trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520W2k%2520trunk/builds/173 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon Build had warnings: warnings test Excerpt from the test logfile: 2 tests failed: test_os test_urllib ====================================================================== ERROR: test_makedir (test.test_os.MakedirTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 384, in setUp os.mkdir(test_support.TESTFN) WindowsError: [Error 183] Cannot create a file when that file already exists: '@test' ====================================================================== ERROR: test_access (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 451, in test_access self.assertRaises(WindowsError, os.utime, test_support.TESTFN, 0) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\unittest.py", line 329, in failUnlessRaises callableObj(*args, **kwargs) TypeError: utime() arg 2 must be a tuple (atime, mtime) ====================================================================== FAIL: test_traversal (test.test_os.WalkTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 313, in test_traversal self.assertEqual(len(all), 4) AssertionError: 5 != 4 ====================================================================== FAIL: test_chdir (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 442, in test_chdir self.assertRaises(WindowsError, os.chdir, test_support.TESTFN) AssertionError: WindowsError not raised Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 460, in __bootstrap self.run() File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\bsddb\test\test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\bsddb\dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 460, in __bootstrap self.run() File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\bsddb\test\test_thread.py", line 260, in writerThread self.assertEqual(data, self.makeData(key)) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\unittest.py", line 343, in failUnlessEqual (msg or '%r != %r' % (first, second)) AssertionError: None != '2000-2000-2000-2000-2000' Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 460, in __bootstrap self.run() File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\bsddb\test\test_thread.py", line 260, in writerThread self.assertEqual(data, self.makeData(key)) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\unittest.py", line 343, in failUnlessEqual (msg or '%r != %r' % (first, second)) AssertionError: None != '0002-0002-0002-0002-0002' Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 460, in __bootstrap self.run() File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\bsddb\test\test_thread.py", line 260, in writerThread self.assertEqual(data, self.makeData(key)) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\unittest.py", line 343, in failUnlessEqual (msg or '%r != %r' % (first, second)) AssertionError: None != '1000-1000-1000-1000-1000' sincerely, -The Buildbot From python-checkins at python.org Sun Apr 1 22:46:18 2007 From: python-checkins at python.org (collin.winter) Date: Sun, 1 Apr 2007 22:46:18 +0200 (CEST) Subject: [Python-checkins] r54648 - in sandbox/trunk/2to3: fixes/util.py tests/test_util.py Message-ID: <20070401204618.8252D1E4007@bag.python.org> Author: collin.winter Date: Sun Apr 1 22:46:14 2007 New Revision: 54648 Modified: sandbox/trunk/2to3/fixes/util.py sandbox/trunk/2to3/tests/test_util.py Log: Add more tests and nested control structure support to fixes.util.find_binding(). Modified: sandbox/trunk/2to3/fixes/util.py ============================================================================== --- sandbox/trunk/2to3/fixes/util.py (original) +++ sandbox/trunk/2to3/fixes/util.py Sun Apr 1 22:46:14 2007 @@ -117,17 +117,38 @@ ### The following functions are to find bindings in a suite ########################################################### +def make_suite(node): + if node.type == syms.suite: + return node + node = node.clone() + parent, node.parent = node.parent, None + suite = Node(syms.suite, [node]) + suite.parent = parent + return suite + _def_syms = set([syms.classdef, syms.funcdef]) def find_binding(name, node): for child in node.children: if child.type == syms.for_stmt: if _find(name, child.children[1]): return child - elif _find(name, child.children[-1]): - return child + n = find_binding(name, make_suite(child.children[-1])) + if n: + return n elif child.type in (syms.if_stmt, syms.while_stmt): - if _find(name, child.children[-1]): - return child + n = find_binding(name, make_suite(child.children[-1])) + if n: + return n + elif child.type == syms.try_stmt: + n = find_binding(name, make_suite(child.children[2])) + if n: + return n + for i, kid in enumerate(child.children[3:]): + if kid.type == token.COLON and kid.value == ":": + # i+3 is the colon, i+4 is the suite + n = find_binding(name, make_suite(child.children[i+4])) + if n: + return n elif child.type in _def_syms and child.children[1].value == name: return child elif _is_import_binding(child, name): Modified: sandbox/trunk/2to3/tests/test_util.py ============================================================================== --- sandbox/trunk/2to3/tests/test_util.py (original) +++ sandbox/trunk/2to3/tests/test_util.py Sun Apr 1 22:46:14 2007 @@ -101,7 +101,7 @@ self.failUnless(self.find_binding("a", "(c, (d, a), b) = foo()")) self.failUnless(self.find_binding("a", "(a, b) = foo().foo.foo[6][foo]")) self.failIf(self.find_binding("a", "(foo, b) = (b, a)")) - self.failIf(self.find_binding("a", "(foo, b, c) = (a, b, c)")) + self.failIf(self.find_binding("a", "(foo, (b, c)) = (a, b, c)")) def test_list_assignment(self): self.failUnless(self.find_binding("a", "[a] = b")) @@ -109,7 +109,7 @@ self.failUnless(self.find_binding("a", "[c, [d, a], b] = foo()")) self.failUnless(self.find_binding("a", "[a, b] = foo().foo.foo[a][foo]")) self.failIf(self.find_binding("a", "[foo, b] = (b, a)")) - self.failIf(self.find_binding("a", "[foo, b, c] = (a, b, c)")) + self.failIf(self.find_binding("a", "[foo, [b, c]] = (a, b, c)")) def test_invalid_assignments(self): self.failIf(self.find_binding("a", "foo.a = 5")) @@ -157,6 +157,12 @@ self.failIf(self.find_binding("a", "def d(a): pass")) self.failIf(self.find_binding("a", "def d(): a = 7")) + s = """ + def d(): + def a(): + pass""" + self.failIf(self.find_binding("a", s)) + def test_class_def(self): self.failUnless(self.find_binding("a", "class a: pass")) self.failUnless(self.find_binding("a", "class a(): pass")) @@ -169,6 +175,12 @@ self.failIf(self.find_binding("a", "class d(b, **a): pass")) self.failIf(self.find_binding("a", "class d: a = 7")) + s = """ + class d(): + class a(): + pass""" + self.failIf(self.find_binding("a", s)) + def test_for(self): self.failUnless(self.find_binding("a", "for a in r: pass")) self.failUnless(self.find_binding("a", "for a, b in r: pass")) @@ -176,14 +188,266 @@ self.failUnless(self.find_binding("a", "for c, (a,) in r: pass")) self.failUnless(self.find_binding("a", "for c, (a, b) in r: pass")) self.failUnless(self.find_binding("a", "for c in r: a = c")) + self.failIf(self.find_binding("a", "for c in a: pass")) + + def test_for_nested(self): + s = """ + for b in r: + for a in b: + pass""" + self.failUnless(self.find_binding("a", s)) + + s = """ + for b in r: + for a, c in b: + pass""" + self.failUnless(self.find_binding("a", s)) + + s = """ + for b in r: + for (a, c) in b: + pass""" + self.failUnless(self.find_binding("a", s)) + + s = """ + for b in r: + for (a,) in b: + pass""" + self.failUnless(self.find_binding("a", s)) + + s = """ + for b in r: + for c, (a, d) in b: + pass""" + self.failUnless(self.find_binding("a", s)) + + s = """ + for b in r: + for c in b: + a = 7""" + self.failUnless(self.find_binding("a", s)) + + s = """ + for b in r: + for c in b: + d = a""" + self.failIf(self.find_binding("a", s)) + + s = """ + for b in r: + for c in a: + d = 7""" + self.failIf(self.find_binding("a", s)) def test_if(self): self.failUnless(self.find_binding("a", "if b in r: a = c")) self.failIf(self.find_binding("a", "if a in r: d = e")) + + def test_if_nested(self): + s = """ + if b in r: + if c in d: + a = c""" + self.failUnless(self.find_binding("a", s)) + + s = """ + if b in r: + if c in d: + c = a""" + self.failIf(self.find_binding("a", s)) def test_while(self): self.failUnless(self.find_binding("a", "while b in r: a = c")) self.failIf(self.find_binding("a", "while a in r: d = e")) + + def test_while_nested(self): + s = """ + while b in r: + while c in d: + a = c""" + self.failUnless(self.find_binding("a", s)) + + s = """ + while b in r: + while c in d: + c = a""" + self.failIf(self.find_binding("a", s)) + + def test_try_except(self): + s = """ + try: + a = 6 + except: + b = 8""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + except: + a = 6""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + except KeyError: + pass + except: + a = 6""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + except: + b = 6""" + self.failIf(self.find_binding("a", s)) + + def test_try_except_nested(self): + s = """ + try: + try: + a = 6 + except: + pass + except: + b = 8""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + except: + try: + a = 6 + except: + pass""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + except: + try: + pass + except: + a = 6""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + try: + b = 8 + except KeyError: + pass + except: + a = 6 + except: + pass""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + pass + except: + try: + b = 8 + except KeyError: + pass + except: + a = 6""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + except: + b = 6""" + self.failIf(self.find_binding("a", s)) + + s = """ + try: + try: + b = 8 + except: + c = d + except: + try: + b = 6 + except: + t = 8 + except: + o = y""" + self.failIf(self.find_binding("a", s)) + + def test_try_except_finally(self): + s = """ + try: + c = 6 + except: + b = 8 + finally: + a = 9""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + finally: + a = 6""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + finally: + b = 6""" + self.failIf(self.find_binding("a", s)) + + s = """ + try: + b = 8 + except: + b = 9 + finally: + b = 6""" + self.failIf(self.find_binding("a", s)) + + def test_try_except_finally_nested(self): + s = """ + try: + c = 6 + except: + b = 8 + finally: + try: + a = 9 + except: + b = 9 + finally: + c = 9""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + finally: + try: + pass + finally: + a = 6""" + self.failUnless(self.find_binding("a", s)) + + s = """ + try: + b = 8 + finally: + try: + b = 6 + finally: + b = 7""" + self.failIf(self.find_binding("a", s)) if __name__ == "__main__": From python-checkins at python.org Sun Apr 1 23:29:18 2007 From: python-checkins at python.org (georg.brandl) Date: Sun, 1 Apr 2007 23:29:18 +0200 (CEST) Subject: [Python-checkins] r54649 - in python/trunk/Doc: lib/libbsddb.tex lib/libcgitb.tex lib/libcodecs.tex lib/libcollections.tex lib/libconsts.tex lib/libcursespanel.tex lib/libdl.tex lib/libdoctest.tex lib/libdumbdbm.tex lib/libetree.tex lib/libhmac.tex lib/liblogging.tex lib/libmmap.tex lib/libpoplib.tex lib/libselect.tex lib/libsocket.tex lib/libsqlite3.tex lib/libwebbrowser.tex lib/libwinreg.tex lib/libzlib.tex mac/libframework.tex Message-ID: <20070401212918.8091F1E4007@bag.python.org> Author: georg.brandl Date: Sun Apr 1 23:29:15 2007 New Revision: 54649 Modified: python/trunk/Doc/lib/libbsddb.tex python/trunk/Doc/lib/libcgitb.tex python/trunk/Doc/lib/libcodecs.tex python/trunk/Doc/lib/libcollections.tex python/trunk/Doc/lib/libconsts.tex python/trunk/Doc/lib/libcursespanel.tex python/trunk/Doc/lib/libdl.tex python/trunk/Doc/lib/libdoctest.tex python/trunk/Doc/lib/libdumbdbm.tex python/trunk/Doc/lib/libetree.tex python/trunk/Doc/lib/libhmac.tex python/trunk/Doc/lib/liblogging.tex python/trunk/Doc/lib/libmmap.tex python/trunk/Doc/lib/libpoplib.tex python/trunk/Doc/lib/libselect.tex python/trunk/Doc/lib/libsocket.tex python/trunk/Doc/lib/libsqlite3.tex python/trunk/Doc/lib/libwebbrowser.tex python/trunk/Doc/lib/libwinreg.tex python/trunk/Doc/lib/libzlib.tex python/trunk/Doc/mac/libframework.tex Log: Fix a lot of markup and meta-information glitches. Modified: python/trunk/Doc/lib/libbsddb.tex ============================================================================== --- python/trunk/Doc/lib/libbsddb.tex (original) +++ python/trunk/Doc/lib/libbsddb.tex Sun Apr 1 23:29:15 2007 @@ -113,23 +113,23 @@ the methods listed below. \versionchanged[Added dictionary methods]{2.3.1} -\begin{methoddesc}{close}{} +\begin{methoddesc}[bsddbobject]{close}{} Close the underlying file. The object can no longer be accessed. Since there is no open \method{open} method for these objects, to open the file again a new \module{bsddb} module open function must be called. \end{methoddesc} -\begin{methoddesc}{keys}{} +\begin{methoddesc}[bsddbobject]{keys}{} Return the list of keys contained in the DB file. The order of the list is unspecified and should not be relied on. In particular, the order of the list returned is different for different file formats. \end{methoddesc} -\begin{methoddesc}{has_key}{key} +\begin{methoddesc}[bsddbobject]{has_key}{key} Return \code{1} if the DB file contains the argument as a key. \end{methoddesc} -\begin{methoddesc}{set_location}{key} +\begin{methoddesc}[bsddbobject]{set_location}{key} Set the cursor to the item indicated by \var{key} and return a tuple containing the key and its value. For binary tree databases (opened using \function{btopen()}), if \var{key} does not actually exist in @@ -139,32 +139,32 @@ database. \end{methoddesc} -\begin{methoddesc}{first}{} +\begin{methoddesc}[bsddbobject]{first}{} Set the cursor to the first item in the DB file and return it. The order of keys in the file is unspecified, except in the case of B-Tree databases. This method raises \exception{bsddb.error} if the database is empty. \end{methoddesc} -\begin{methoddesc}{next}{} +\begin{methoddesc}[bsddbobject]{next}{} Set the cursor to the next item in the DB file and return it. The order of keys in the file is unspecified, except in the case of B-Tree databases. \end{methoddesc} -\begin{methoddesc}{previous}{} +\begin{methoddesc}[bsddbobject]{previous}{} Set the cursor to the previous item in the DB file and return it. The order of keys in the file is unspecified, except in the case of B-Tree databases. This is not supported on hashtable databases (those opened with \function{hashopen()}). \end{methoddesc} -\begin{methoddesc}{last}{} +\begin{methoddesc}[bsddbobject]{last}{} Set the cursor to the last item in the DB file and return it. The order of keys in the file is unspecified. This is not supported on hashtable databases (those opened with \function{hashopen()}). This method raises \exception{bsddb.error} if the database is empty. \end{methoddesc} -\begin{methoddesc}{sync}{} +\begin{methoddesc}[bsddbobject]{sync}{} Synchronize the database on disk. \end{methoddesc} Modified: python/trunk/Doc/lib/libcgitb.tex ============================================================================== --- python/trunk/Doc/lib/libcgitb.tex (original) +++ python/trunk/Doc/lib/libcgitb.tex Sun Apr 1 23:29:15 2007 @@ -38,7 +38,7 @@ context\optional{, format}}}}} This function causes the \module{cgitb} module to take over the interpreter's default handling for exceptions by setting the - value of \code{\refmodule{sys}.excepthook}. + value of \member{\refmodule{sys}.excepthook}. \withsubitem{(in module sys)}{\ttindex{excepthook()}} The optional argument \var{display} defaults to \code{1} and can be set @@ -61,7 +61,7 @@ report it using \module{cgitb}. The optional \var{info} argument should be a 3-tuple containing an exception type, exception value, and traceback object, exactly like the tuple returned by - \code{\refmodule{sys}.exc_info()}. If the \var{info} argument + \function{\refmodule{sys}.exc_info()}. If the \var{info} argument is not supplied, the current exception is obtained from - \code{\refmodule{sys}.exc_info()}. + \function{\refmodule{sys}.exc_info()}. \end{funcdesc} Modified: python/trunk/Doc/lib/libcodecs.tex ============================================================================== --- python/trunk/Doc/lib/libcodecs.tex (original) +++ python/trunk/Doc/lib/libcodecs.tex Sun Apr 1 23:29:15 2007 @@ -307,7 +307,7 @@ The \class{Codec} class defines these methods which also define the function interfaces of the stateless encoder and decoder: -\begin{methoddesc}{encode}{input\optional{, errors}} +\begin{methoddesc}[Codec]{encode}{input\optional{, errors}} Encodes the object \var{input} and returns a tuple (output object, length consumed). While codecs are not restricted to use with Unicode, in a Unicode context, encoding converts a Unicode object to a plain string @@ -325,7 +325,7 @@ empty object of the output object type in this situation. \end{methoddesc} -\begin{methoddesc}{decode}{input\optional{, errors}} +\begin{methoddesc}[Codec]{decode}{input\optional{, errors}} Decodes the object \var{input} and returns a tuple (output object, length consumed). In a Unicode context, decoding converts a plain string encoded using a particular character set encoding to a Unicode object. @@ -1197,9 +1197,8 @@ \lineiv{idna} {} {Unicode string} - {Implements \rfc{3490}. - \versionadded{2.3} - See also \refmodule{encodings.idna}} + {Implements \rfc{3490}, + see also \refmodule{encodings.idna}} \lineiv{mbcs} {dbcs} @@ -1214,8 +1213,7 @@ \lineiv{punycode} {} {Unicode string} - {Implements \rfc{3492}. - \versionadded{2.3}} + {Implements \rfc{3492}} \lineiv{quopri_codec} {quopri, quoted-printable, quotedprintable} @@ -1269,6 +1267,8 @@ \end{tableiv} +\versionadded[The \code{idna} and \code{punycode} encodings]{2.3} + \subsection{\module{encodings.idna} --- Internationalized Domain Names in Applications} Modified: python/trunk/Doc/lib/libcollections.tex ============================================================================== --- python/trunk/Doc/lib/libcollections.tex (original) +++ python/trunk/Doc/lib/libcollections.tex Sun Apr 1 23:29:15 2007 @@ -17,7 +17,7 @@ \subsection{\class{deque} objects \label{deque-objects}} -\begin{funcdesc}{deque}{\optional{iterable}} +\begin{classdesc}{deque}{\optional{iterable}} Returns a new deque object initialized left-to-right (using \method{append()}) with data from \var{iterable}. If \var{iterable} is not specified, the new deque is empty. @@ -32,7 +32,7 @@ for \samp{pop(0)} and \samp{insert(0, v)} operations which change both the size and position of the underlying data representation. \versionadded{2.4} -\end{funcdesc} +\end{classdesc} Deque objects support the following methods: Modified: python/trunk/Doc/lib/libconsts.tex ============================================================================== --- python/trunk/Doc/lib/libconsts.tex (original) +++ python/trunk/Doc/lib/libconsts.tex Sun Apr 1 23:29:15 2007 @@ -13,7 +13,7 @@ \end{datadesc} \begin{datadesc}{None} - The sole value of \code{\refmodule{types}.NoneType}. \code{None} is + The sole value of \member{\refmodule{types}.NoneType}. \code{None} is frequently used to represent the absence of a value, as when default arguments are not passed to a function. \end{datadesc} Modified: python/trunk/Doc/lib/libcursespanel.tex ============================================================================== --- python/trunk/Doc/lib/libcursespanel.tex (original) +++ python/trunk/Doc/lib/libcursespanel.tex Sun Apr 1 23:29:15 2007 @@ -45,52 +45,52 @@ Panel objects have the following methods: -\begin{methoddesc}{above}{} +\begin{methoddesc}[Panel]{above}{} Returns the panel above the current panel. \end{methoddesc} -\begin{methoddesc}{below}{} +\begin{methoddesc}[Panel]{below}{} Returns the panel below the current panel. \end{methoddesc} -\begin{methoddesc}{bottom}{} +\begin{methoddesc}[Panel]{bottom}{} Push the panel to the bottom of the stack. \end{methoddesc} -\begin{methoddesc}{hidden}{} +\begin{methoddesc}[Panel]{hidden}{} Returns true if the panel is hidden (not visible), false otherwise. \end{methoddesc} -\begin{methoddesc}{hide}{} +\begin{methoddesc}[Panel]{hide}{} Hide the panel. This does not delete the object, it just makes the window on screen invisible. \end{methoddesc} -\begin{methoddesc}{move}{y, x} +\begin{methoddesc}[Panel]{move}{y, x} Move the panel to the screen coordinates \code{(\var{y}, \var{x})}. \end{methoddesc} -\begin{methoddesc}{replace}{win} +\begin{methoddesc}[Panel]{replace}{win} Change the window associated with the panel to the window \var{win}. \end{methoddesc} -\begin{methoddesc}{set_userptr}{obj} +\begin{methoddesc}[Panel]{set_userptr}{obj} Set the panel's user pointer to \var{obj}. This is used to associate an arbitrary piece of data with the panel, and can be any Python object. \end{methoddesc} -\begin{methoddesc}{show}{} +\begin{methoddesc}[Panel]{show}{} Display the panel (which might have been hidden). \end{methoddesc} -\begin{methoddesc}{top}{} +\begin{methoddesc}[Panel]{top}{} Push panel to the top of the stack. \end{methoddesc} -\begin{methoddesc}{userptr}{} +\begin{methoddesc}[Panel]{userptr}{} Returns the user pointer for the panel. This might be any Python object. \end{methoddesc} -\begin{methoddesc}{window}{} +\begin{methoddesc}[Panel]{window}{} Returns the window object associated with the panel. \end{methoddesc} Modified: python/trunk/Doc/lib/libdl.tex ============================================================================== --- python/trunk/Doc/lib/libdl.tex (original) +++ python/trunk/Doc/lib/libdl.tex Sun Apr 1 23:29:15 2007 @@ -67,11 +67,11 @@ Dl objects, as returned by \function{open()} above, have the following methods: -\begin{methoddesc}{close}{} +\begin{methoddesc}[dl]{close}{} Free all resources, except the memory. \end{methoddesc} -\begin{methoddesc}{sym}{name} +\begin{methoddesc}[dl]{sym}{name} Return the pointer for the function named \var{name}, as a number, if it exists in the referenced shared object, otherwise \code{None}. This is useful in code like: @@ -87,7 +87,7 @@ \NULL{} pointer) \end{methoddesc} -\begin{methoddesc}{call}{name\optional{, arg1\optional{, arg2\ldots}}} +\begin{methoddesc}[dl]{call}{name\optional{, arg1\optional{, arg2\ldots}}} Call the function named \var{name} in the referenced shared object. The arguments must be either Python integers, which will be passed as is, Python strings, to which a pointer will be passed, Modified: python/trunk/Doc/lib/libdoctest.tex ============================================================================== --- python/trunk/Doc/lib/libdoctest.tex (original) +++ python/trunk/Doc/lib/libdoctest.tex Sun Apr 1 23:29:15 2007 @@ -1741,7 +1741,7 @@ >>> \end{verbatim} - \versionchanged[The ability to use \code{\refmodule{pdb}.set_trace()} + \versionchanged[The ability to use \function{\refmodule{pdb}.set_trace()} usefully inside doctests was added]{2.4} \end{itemize} @@ -1825,10 +1825,10 @@ used. If \var{pm} has a true value, the script file is run directly, and the debugger gets involved only if the script terminates via raising an unhandled exception. If it does, then post-mortem debugging is invoked, - via \code{\refmodule{pdb}.post_mortem()}, passing the traceback object + via \function{\refmodule{pdb}.post_mortem()}, passing the traceback object from the unhandled exception. If \var{pm} is not specified, or is false, the script is run under the debugger from the start, via passing an - appropriate \function{execfile()} call to \code{\refmodule{pdb}.run()}. + appropriate \function{execfile()} call to \function{\refmodule{pdb}.run()}. \versionadded{2.3} Modified: python/trunk/Doc/lib/libdumbdbm.tex ============================================================================== --- python/trunk/Doc/lib/libdumbdbm.tex (original) +++ python/trunk/Doc/lib/libdumbdbm.tex Sun Apr 1 23:29:15 2007 @@ -57,7 +57,7 @@ In addition to the methods provided by the \class{UserDict.DictMixin} class, \class{dumbdbm} objects provide the following methods. -\begin{methoddesc}{sync}{} +\begin{methoddesc}[dumbdbm]{sync}{} Synchronize the on-disk directory and data files. This method is called by the \method{sync} method of \class{Shelve} objects. \end{methoddesc} Modified: python/trunk/Doc/lib/libetree.tex ============================================================================== --- python/trunk/Doc/lib/libetree.tex (original) +++ python/trunk/Doc/lib/libetree.tex Sun Apr 1 23:29:15 2007 @@ -144,12 +144,12 @@ Element objects returned by Element or SubElement have the following methods and attributes. -\begin{memberdesc}{tag} +\begin{memberdesc}[Element]{tag} A string identifying what kind of data this element represents (the element type, in other words). \end{memberdesc} -\begin{memberdesc}{text} +\begin{memberdesc}[Element]{text} The \var{text} attribute can be used to hold additional data associated with the element. As the name implies this attribute is usually a string but may be any @@ -158,7 +158,7 @@ any text found between the element tags. \end{memberdesc} -\begin{memberdesc}{tail} +\begin{memberdesc}[Element]{tail} The \var{tail} attribute can be used to hold additional data associated with the element. This attribute is usually a string but may be any application-specific object. @@ -166,7 +166,7 @@ any text found after the element's end tag and before the next tag. \end{memberdesc} -\begin{memberdesc}{attrib} +\begin{memberdesc}[Element]{attrib} A dictionary containing the element's attributes. Note that while the \var{attrib} value is always a real mutable Python dictionary, an ElementTree implementation may choose to use another @@ -177,52 +177,52 @@ The following dictionary-like methods work on the element attributes. -\begin{methoddesc}{clear}{} +\begin{methoddesc}[Element]{clear}{} Resets an element. This function removes all subelements, clears all attributes, and sets the text and tail attributes to None. \end{methoddesc} -\begin{methoddesc}{get}{key\optional{, default=None}} +\begin{methoddesc}[Element]{get}{key\optional{, default=None}} Gets the element attribute named \var{key}. Returns the attribute value, or \var{default} if the attribute was not found. \end{methoddesc} -\begin{methoddesc}{items}{} +\begin{methoddesc}[Element]{items}{} Returns the element attributes as a sequence of (name, value) pairs. The attributes are returned in an arbitrary order. \end{methoddesc} -\begin{methoddesc}{keys}{} +\begin{methoddesc}[Element]{keys}{} Returns the elements attribute names as a list. The names are returned in an arbitrary order. \end{methoddesc} -\begin{methoddesc}{set}{key, value} +\begin{methoddesc}[Element]{set}{key, value} Set the attribute \var{key} on the element to \var{value}. \end{methoddesc} The following methods work on the element's children (subelements). -\begin{methoddesc}{append}{subelement} +\begin{methoddesc}[Element]{append}{subelement} Adds the element \var{subelement} to the end of this elements internal list of subelements. \end{methoddesc} -\begin{methoddesc}{find}{match} +\begin{methoddesc}[Element]{find}{match} Finds the first subelement matching \var{match}. \var{match} may be a tag name or path. Returns an element instance or \code{None}. \end{methoddesc} -\begin{methoddesc}{findall}{match} +\begin{methoddesc}[Element]{findall}{match} Finds all subelements matching \var{match}. \var{match} may be a tag name or path. Returns an iterable yielding all matching elements in document order. \end{methoddesc} -\begin{methoddesc}{findtext}{condition\optional{, default=None}} +\begin{methoddesc}[Element]{findtext}{condition\optional{, default=None}} Finds text for the first subelement matching \var{condition}. \var{condition} may be a tag name or path. Returns the text content of the first matching element, or @@ -230,11 +230,11 @@ matching element has no text content an empty string is returned. \end{methoddesc} -\begin{methoddesc}{getchildren}{} +\begin{methoddesc}[Element]{getchildren}{} Returns all subelements. The elements are returned in document order. \end{methoddesc} -\begin{methoddesc}{getiterator}{\optional{tag=None}} +\begin{methoddesc}[Element]{getiterator}{\optional{tag=None}} Creates a tree iterator with the current element as the root. The iterator iterates over this element and all elements below it that match the given tag. If tag @@ -243,16 +243,16 @@ order. \end{methoddesc} -\begin{methoddesc}{insert}{index, element} +\begin{methoddesc}[Element]{insert}{index, element} Inserts a subelement at the given position in this element. \end{methoddesc} -\begin{methoddesc}{makeelement}{tag, attrib} +\begin{methoddesc}[Element]{makeelement}{tag, attrib} Creates a new element object of the same type as this element. Do not call this method, use the SubElement factory function instead. \end{methoddesc} -\begin{methoddesc}{remove}{subelement} +\begin{methoddesc}[Element]{remove}{subelement} Removes \var{subelement} from the element. Unlike the findXXX methods this method compares elements based on the instance identity, not on tag value or contents. Modified: python/trunk/Doc/lib/libhmac.tex ============================================================================== --- python/trunk/Doc/lib/libhmac.tex (original) +++ python/trunk/Doc/lib/libhmac.tex Sun Apr 1 23:29:15 2007 @@ -15,7 +15,7 @@ Return a new hmac object. If \var{msg} is present, the method call \code{update(\var{msg})} is made. \var{digestmod} is the digest constructor or module for the HMAC object to use. It defaults to - the \code{\refmodule{hashlib}.md5} constructor. \note{The md5 hash + the \function{\refmodule{hashlib}.md5} constructor. \note{The md5 hash has known weaknesses but remains the default for backwards compatibility. Choose a better one for your application.} \end{funcdesc} Modified: python/trunk/Doc/lib/liblogging.tex ============================================================================== --- python/trunk/Doc/lib/liblogging.tex (original) +++ python/trunk/Doc/lib/liblogging.tex Sun Apr 1 23:29:15 2007 @@ -364,13 +364,13 @@ never instantiated directly, but always through the module-level function \function{logging.getLogger(name)}. -\begin{datadesc}{propagate} +\begin{memberdesc}[Logger]{propagate} If this evaluates to false, logging messages are not passed by this logger or by child loggers to higher level (ancestor) loggers. The constructor sets this attribute to 1. -\end{datadesc} +\end{memberdesc} -\begin{methoddesc}{setLevel}{lvl} +\begin{methoddesc}[Logger]{setLevel}{lvl} Sets the threshold for this logger to \var{lvl}. Logging messages which are less severe than \var{lvl} will be ignored. When a logger is created, the level is set to \constant{NOTSET} (which causes all messages @@ -393,21 +393,21 @@ as the effective level. \end{methoddesc} -\begin{methoddesc}{isEnabledFor}{lvl} +\begin{methoddesc}[Logger]{isEnabledFor}{lvl} Indicates if a message of severity \var{lvl} would be processed by this logger. This method checks first the module-level level set by \function{logging.disable(lvl)} and then the logger's effective level as determined by \method{getEffectiveLevel()}. \end{methoddesc} -\begin{methoddesc}{getEffectiveLevel}{} +\begin{methoddesc}[Logger]{getEffectiveLevel}{} Indicates the effective level for this logger. If a value other than \constant{NOTSET} has been set using \method{setLevel()}, it is returned. Otherwise, the hierarchy is traversed towards the root until a value other than \constant{NOTSET} is found, and that value is returned. \end{methoddesc} -\begin{methoddesc}{debug}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{debug}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{DEBUG} on this logger. The \var{msg} is the message format string, and the \var{args} are the arguments which are merged into \var{msg} using the string formatting @@ -462,67 +462,67 @@ \end{methoddesc} -\begin{methoddesc}{info}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{info}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{INFO} on this logger. The arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{warning}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{warning}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{WARNING} on this logger. The arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{error}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{error}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{ERROR} on this logger. The arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{critical}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{critical}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{CRITICAL} on this logger. The arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{log}{lvl, msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{log}{lvl, msg\optional{, *args\optional{, **kwargs}}} Logs a message with integer level \var{lvl} on this logger. The other arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{exception}{msg\optional{, *args}} +\begin{methoddesc}[Logger]{exception}{msg\optional{, *args}} Logs a message with level \constant{ERROR} on this logger. The arguments are interpreted as for \method{debug()}. Exception info is added to the logging message. This method should only be called from an exception handler. \end{methoddesc} -\begin{methoddesc}{addFilter}{filt} +\begin{methoddesc}[Logger]{addFilter}{filt} Adds the specified filter \var{filt} to this logger. \end{methoddesc} -\begin{methoddesc}{removeFilter}{filt} +\begin{methoddesc}[Logger]{removeFilter}{filt} Removes the specified filter \var{filt} from this logger. \end{methoddesc} -\begin{methoddesc}{filter}{record} +\begin{methoddesc}[Logger]{filter}{record} Applies this logger's filters to the record and returns a true value if the record is to be processed. \end{methoddesc} -\begin{methoddesc}{addHandler}{hdlr} +\begin{methoddesc}[Logger]{addHandler}{hdlr} Adds the specified handler \var{hdlr} to this logger. \end{methoddesc} -\begin{methoddesc}{removeHandler}{hdlr} +\begin{methoddesc}[Logger]{removeHandler}{hdlr} Removes the specified handler \var{hdlr} from this logger. \end{methoddesc} -\begin{methoddesc}{findCaller}{} +\begin{methoddesc}[Logger]{findCaller}{} Finds the caller's source filename and line number. Returns the filename, line number and function name as a 3-element tuple. \versionchanged[The function name was added. In earlier versions, the filename and line number were returned as a 2-element tuple.]{2.5} \end{methoddesc} -\begin{methoddesc}{handle}{record} +\begin{methoddesc}[Logger]{handle}{record} Handles a record by passing it to all handlers associated with this logger and its ancestors (until a false value of \var{propagate} is found). This method is used for unpickled records received from a socket, as well @@ -530,8 +530,8 @@ \method{filter()}. \end{methoddesc} -\begin{methoddesc}{makeRecord}{name, lvl, fn, lno, msg, args, exc_info - \optional{, func, extra}} +\begin{methoddesc}[Logger]{makeRecord}{name, lvl, fn, lno, msg, args, exc_info + \optional{, func, extra}} This is a factory method which can be overridden in subclasses to create specialized \class{LogRecord} instances. \versionchanged[\var{func} and \var{extra} were added]{2.5} @@ -875,66 +875,66 @@ base for more useful subclasses. However, the \method{__init__()} method in subclasses needs to call \method{Handler.__init__()}. -\begin{methoddesc}{__init__}{level=\constant{NOTSET}} +\begin{methoddesc}[Handler]{__init__}{level=\constant{NOTSET}} Initializes the \class{Handler} instance by setting its level, setting the list of filters to the empty list and creating a lock (using \method{createLock()}) for serializing access to an I/O mechanism. \end{methoddesc} -\begin{methoddesc}{createLock}{} +\begin{methoddesc}[Handler]{createLock}{} Initializes a thread lock which can be used to serialize access to underlying I/O functionality which may not be threadsafe. \end{methoddesc} -\begin{methoddesc}{acquire}{} +\begin{methoddesc}[Handler]{acquire}{} Acquires the thread lock created with \method{createLock()}. \end{methoddesc} -\begin{methoddesc}{release}{} +\begin{methoddesc}[Handler]{release}{} Releases the thread lock acquired with \method{acquire()}. \end{methoddesc} -\begin{methoddesc}{setLevel}{lvl} +\begin{methoddesc}[Handler]{setLevel}{lvl} Sets the threshold for this handler to \var{lvl}. Logging messages which are less severe than \var{lvl} will be ignored. When a handler is created, the level is set to \constant{NOTSET} (which causes all messages to be processed). \end{methoddesc} -\begin{methoddesc}{setFormatter}{form} +\begin{methoddesc}[Handler]{setFormatter}{form} Sets the \class{Formatter} for this handler to \var{form}. \end{methoddesc} -\begin{methoddesc}{addFilter}{filt} +\begin{methoddesc}[Handler]{addFilter}{filt} Adds the specified filter \var{filt} to this handler. \end{methoddesc} -\begin{methoddesc}{removeFilter}{filt} +\begin{methoddesc}[Handler]{removeFilter}{filt} Removes the specified filter \var{filt} from this handler. \end{methoddesc} -\begin{methoddesc}{filter}{record} +\begin{methoddesc}[Handler]{filter}{record} Applies this handler's filters to the record and returns a true value if the record is to be processed. \end{methoddesc} -\begin{methoddesc}{flush}{} +\begin{methoddesc}[Handler]{flush}{} Ensure all logging output has been flushed. This version does nothing and is intended to be implemented by subclasses. \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[Handler]{close}{} Tidy up any resources used by the handler. This version does nothing and is intended to be implemented by subclasses. \end{methoddesc} -\begin{methoddesc}{handle}{record} +\begin{methoddesc}[Handler]{handle}{record} Conditionally emits the specified logging record, depending on filters which may have been added to the handler. Wraps the actual emission of the record with acquisition/release of the I/O thread lock. \end{methoddesc} -\begin{methoddesc}{handleError}{record} +\begin{methoddesc}[Handler]{handleError}{record} This method should be called from handlers when an exception is encountered during an \method{emit()} call. By default it does nothing, which means that exceptions get silently ignored. This is what is @@ -945,12 +945,12 @@ processed when the exception occurred. \end{methoddesc} -\begin{methoddesc}{format}{record} +\begin{methoddesc}[Handler]{format}{record} Do formatting for a record - if a formatter is set, use it. Otherwise, use the default formatter for the module. \end{methoddesc} -\begin{methoddesc}{emit}{record} +\begin{methoddesc}[Handler]{emit}{record} Do whatever it takes to actually log the specified logging record. This version is intended to be implemented by subclasses and so raises a \exception{NotImplementedError}. Modified: python/trunk/Doc/lib/libmmap.tex ============================================================================== --- python/trunk/Doc/lib/libmmap.tex (original) +++ python/trunk/Doc/lib/libmmap.tex Sun Apr 1 23:29:15 2007 @@ -89,18 +89,18 @@ Memory-mapped file objects support the following methods: -\begin{methoddesc}{close}{} +\begin{methoddesc}[mmap]{close}{} Close the file. Subsequent calls to other methods of the object will result in an exception being raised. \end{methoddesc} -\begin{methoddesc}{find}{string\optional{, start}} +\begin{methoddesc}[mmap]{find}{string\optional{, start}} Returns the lowest index in the object where the substring \var{string} is found. Returns \code{-1} on failure. \var{start} is the index at which the search begins, and defaults to zero. \end{methoddesc} -\begin{methoddesc}{flush}{\optional{offset, size}} +\begin{methoddesc}[mmap]{flush}{\optional{offset, size}} Flushes changes made to the in-memory copy of a file back to disk. Without use of this call there is no guarantee that changes are written back before the object is destroyed. If \var{offset} and @@ -109,36 +109,36 @@ is flushed. \end{methoddesc} -\begin{methoddesc}{move}{\var{dest}, \var{src}, \var{count}} +\begin{methoddesc}[mmap]{move}{\var{dest}, \var{src}, \var{count}} Copy the \var{count} bytes starting at offset \var{src} to the destination index \var{dest}. If the mmap was created with \constant{ACCESS_READ}, then calls to move will throw a \exception{TypeError} exception. \end{methoddesc} -\begin{methoddesc}{read}{\var{num}} +\begin{methoddesc}[mmap]{read}{\var{num}} Return a string containing up to \var{num} bytes starting from the current file position; the file position is updated to point after the bytes that were returned. \end{methoddesc} -\begin{methoddesc}{read_byte}{} +\begin{methoddesc}[mmap]{read_byte}{} Returns a string of length 1 containing the character at the current file position, and advances the file position by 1. \end{methoddesc} -\begin{methoddesc}{readline}{} +\begin{methoddesc}[mmap]{readline}{} Returns a single line, starting at the current file position and up to the next newline. \end{methoddesc} -\begin{methoddesc}{resize}{\var{newsize}} +\begin{methoddesc}[mmap]{resize}{\var{newsize}} Resizes the map and the underlying file, if any. If the mmap was created with \constant{ACCESS_READ} or \constant{ACCESS_COPY}, resizing the map will throw a \exception{TypeError} exception. \end{methoddesc} -\begin{methoddesc}{seek}{pos\optional{, whence}} +\begin{methoddesc}[mmap]{seek}{pos\optional{, whence}} Set the file's current position. \var{whence} argument is optional and defaults to \code{os.SEEK_SET} or \code{0} (absolute file positioning); other values are \code{os.SEEK_CUR} or \code{1} (seek @@ -146,16 +146,16 @@ (seek relative to the file's end). \end{methoddesc} -\begin{methoddesc}{size}{} +\begin{methoddesc}[mmap]{size}{} Return the length of the file, which can be larger than the size of the memory-mapped area. \end{methoddesc} -\begin{methoddesc}{tell}{} +\begin{methoddesc}[mmap]{tell}{} Returns the current position of the file pointer. \end{methoddesc} -\begin{methoddesc}{write}{\var{string}} +\begin{methoddesc}[mmap]{write}{\var{string}} Write the bytes in \var{string} into memory at the current position of the file pointer; the file position is updated to point after the bytes that were written. If the mmap was created with @@ -163,7 +163,7 @@ \exception{TypeError} exception. \end{methoddesc} -\begin{methoddesc}{write_byte}{\var{byte}} +\begin{methoddesc}[mmap]{write_byte}{\var{byte}} Write the single-character string \var{byte} into memory at the current position of the file pointer; the file position is advanced by \code{1}. If the mmap was created with \constant{ACCESS_READ}, Modified: python/trunk/Doc/lib/libpoplib.tex ============================================================================== --- python/trunk/Doc/lib/libpoplib.tex (original) +++ python/trunk/Doc/lib/libpoplib.tex Sun Apr 1 23:29:15 2007 @@ -23,7 +23,7 @@ Note that POP3, though widely supported, is obsolescent. The implementation quality of POP3 servers varies widely, and too many are quite poor. If your mailserver supports IMAP, you would be better off -using the \code{\refmodule{imaplib}.\class{IMAP4}} class, as IMAP +using the \class{\refmodule{imaplib}.IMAP4} class, as IMAP servers tend to be better implemented. A single class is provided by the \module{poplib} module: Modified: python/trunk/Doc/lib/libselect.tex ============================================================================== --- python/trunk/Doc/lib/libselect.tex (original) +++ python/trunk/Doc/lib/libselect.tex Sun Apr 1 23:29:15 2007 @@ -77,7 +77,7 @@ \cfunction{select()} is O(highest file descriptor), while \cfunction{poll()} is O(number of file descriptors). -\begin{methoddesc}{register}{fd\optional{, eventmask}} +\begin{methoddesc}[poll]{register}{fd\optional{, eventmask}} Register a file descriptor with the polling object. Future calls to the \method{poll()} method will then check whether the file descriptor has any pending I/O events. \var{fd} can be either an integer, or an @@ -105,7 +105,7 @@ once. \end{methoddesc} -\begin{methoddesc}{unregister}{fd} +\begin{methoddesc}[poll]{unregister}{fd} Remove a file descriptor being tracked by a polling object. Just like the \method{register()} method, \var{fd} can be an integer or an object with a \method{fileno()} method that returns an integer. @@ -114,7 +114,7 @@ causes a \exception{KeyError} exception to be raised. \end{methoddesc} -\begin{methoddesc}{poll}{\optional{timeout}} +\begin{methoddesc}[poll]{poll}{\optional{timeout}} Polls the set of registered file descriptors, and returns a possibly-empty list containing \code{(\var{fd}, \var{event})} 2-tuples for the descriptors that have events or errors to report. Modified: python/trunk/Doc/lib/libsocket.tex ============================================================================== --- python/trunk/Doc/lib/libsocket.tex (original) +++ python/trunk/Doc/lib/libsocket.tex Sun Apr 1 23:29:15 2007 @@ -14,7 +14,7 @@ papers: \citetitle{An Introductory 4.3BSD Interprocess Communication Tutorial}, by Stuart Sechrest and \citetitle{An Advanced 4.3BSD Interprocess Communication Tutorial}, by Samuel J. Leffler et al, -both in the \citetitle{\UNIX{} Programmer's Manual, Supplementary Documents 1} +both in the \citetitle{UNIX Programmer's Manual, Supplementary Documents 1} (sections PS1:7 and PS1:8). The platform-specific reference material for the various socket-related system calls are also a valuable source of information on the details of socket semantics. For \UNIX, refer @@ -733,23 +733,23 @@ SSL objects have the following methods. -\begin{methoddesc}{write}{s} +\begin{methoddesc}[SSL]{write}{s} Writes the string \var{s} to the on the object's SSL connection. The return value is the number of bytes written. \end{methoddesc} -\begin{methoddesc}{read}{\optional{n}} +\begin{methoddesc}[SSL]{read}{\optional{n}} If \var{n} is provided, read \var{n} bytes from the SSL connection, otherwise read until EOF. The return value is a string of the bytes read. \end{methoddesc} -\begin{methoddesc}{server}{} +\begin{methoddesc}[SSL]{server}{} Returns a string describing the server's certificate. Useful for debugging purposes; do not parse the content of this string because its format can't be parsed unambiguously. \end{methoddesc} -\begin{methoddesc}{issuer}{} +\begin{methoddesc}[SSL]{issuer}{} Returns a string describing the issuer of the server's certificate. Useful for debugging purposes; do not parse the content of this string because its format can't be parsed unambiguously. Modified: python/trunk/Doc/lib/libsqlite3.tex ============================================================================== --- python/trunk/Doc/lib/libsqlite3.tex (original) +++ python/trunk/Doc/lib/libsqlite3.tex Sun Apr 1 23:29:15 2007 @@ -210,37 +210,37 @@ A \class{Connection} instance has the following attributes and methods: \label{sqlite3-Connection-IsolationLevel} -\begin{memberdesc}{isolation_level} +\begin{memberdesc}[Connection]{isolation_level} Get or set the current isolation level. None for autocommit mode or one of "DEFERRED", "IMMEDIATE" or "EXLUSIVE". See ``Controlling Transactions'', section~\ref{sqlite3-Controlling-Transactions}, for a more detailed explanation. \end{memberdesc} -\begin{methoddesc}{cursor}{\optional{cursorClass}} +\begin{methoddesc}[Connection]{cursor}{\optional{cursorClass}} The cursor method accepts a single optional parameter \var{cursorClass}. If supplied, this must be a custom cursor class that extends \class{sqlite3.Cursor}. \end{methoddesc} -\begin{methoddesc}{execute}{sql, \optional{parameters}} +\begin{methoddesc}[Connection]{execute}{sql, \optional{parameters}} This is a nonstandard shortcut that creates an intermediate cursor object by calling the cursor method, then calls the cursor's \method{execute} method with the parameters given. \end{methoddesc} -\begin{methoddesc}{executemany}{sql, \optional{parameters}} +\begin{methoddesc}[Connection]{executemany}{sql, \optional{parameters}} This is a nonstandard shortcut that creates an intermediate cursor object by calling the cursor method, then calls the cursor's \method{executemany} method with the parameters given. \end{methoddesc} -\begin{methoddesc}{executescript}{sql_script} +\begin{methoddesc}[Connection]{executescript}{sql_script} This is a nonstandard shortcut that creates an intermediate cursor object by calling the cursor method, then calls the cursor's \method{executescript} method with the parameters given. \end{methoddesc} -\begin{methoddesc}{create_function}{name, num_params, func} +\begin{methoddesc}[Connection]{create_function}{name, num_params, func} Creates a user-defined function that you can later use from within SQL statements under the function name \var{name}. \var{num_params} is the number @@ -255,7 +255,7 @@ \verbatiminput{sqlite3/md5func.py} \end{methoddesc} -\begin{methoddesc}{create_aggregate}{name, num_params, aggregate_class} +\begin{methoddesc}[Connection]{create_aggregate}{name, num_params, aggregate_class} Creates a user-defined aggregate function. @@ -271,7 +271,7 @@ \verbatiminput{sqlite3/mysumaggr.py} \end{methoddesc} -\begin{methoddesc}{create_collation}{name, callable} +\begin{methoddesc}[Connection]{create_collation}{name, callable} Creates a collation with the specified \var{name} and \var{callable}. The callable will be passed two string arguments. It should return -1 if the first @@ -293,14 +293,14 @@ \end{verbatim} \end{methoddesc} -\begin{methoddesc}{interrupt}{} +\begin{methoddesc}[Connection]{interrupt}{} You can call this method from a different thread to abort any queries that might be executing on the connection. The query will then abort and the caller will get an exception. \end{methoddesc} -\begin{methoddesc}{set_authorizer}{authorizer_callback} +\begin{methoddesc}[Connection]{set_authorizer}{authorizer_callback} This routine registers a callback. The callback is invoked for each attempt to access a column of a table in the database. The callback should return @@ -322,7 +322,7 @@ module. \end{methoddesc} -\begin{memberdesc}{row_factory} +\begin{memberdesc}[Connection]{row_factory} You can change this attribute to a callable that accepts the cursor and the original row as a tuple and will return the real result row. This way, you can implement more advanced ways of returning results, such @@ -341,7 +341,7 @@ % XXX what's a db_row-based solution? \end{memberdesc} -\begin{memberdesc}{text_factory} +\begin{memberdesc}[Connection]{text_factory} Using this attribute you can control what objects are returned for the TEXT data type. By default, this attribute is set to \class{unicode} and the \module{sqlite3} module will return Unicode objects for TEXT. If you want to return @@ -359,7 +359,7 @@ \verbatiminput{sqlite3/text_factory.py} \end{memberdesc} -\begin{memberdesc}{total_changes} +\begin{memberdesc}[Connection]{total_changes} Returns the total number of database rows that have been modified, inserted, or deleted since the database connection was opened. \end{memberdesc} @@ -372,7 +372,7 @@ A \class{Cursor} instance has the following attributes and methods: -\begin{methoddesc}{execute}{sql, \optional{parameters}} +\begin{methoddesc}[Cursor]{execute}{sql, \optional{parameters}} Executes a SQL statement. The SQL statement may be parametrized (i. e. placeholders instead of SQL literals). The \module{sqlite3} module supports two kinds of @@ -394,7 +394,7 @@ \end{methoddesc} -\begin{methoddesc}{executemany}{sql, seq_of_parameters} +\begin{methoddesc}[Cursor]{executemany}{sql, seq_of_parameters} Executes a SQL command against all parameter sequences or mappings found in the sequence \var{sql}. The \module{sqlite3} module also allows using an iterator yielding parameters instead of a sequence. @@ -406,7 +406,7 @@ \verbatiminput{sqlite3/executemany_2.py} \end{methoddesc} -\begin{methoddesc}{executescript}{sql_script} +\begin{methoddesc}[Cursor]{executescript}{sql_script} This is a nonstandard convenience method for executing multiple SQL statements at once. It issues a COMMIT statement first, then executes the SQL script it @@ -419,7 +419,7 @@ \verbatiminput{sqlite3/executescript.py} \end{methoddesc} -\begin{memberdesc}{rowcount} +\begin{memberdesc}[Cursor]{rowcount} Although the \class{Cursor} class of the \module{sqlite3} module implements this attribute, the database engine's own support for the determination of "rows affected"/"rows selected" is quirky. Modified: python/trunk/Doc/lib/libwebbrowser.tex ============================================================================== --- python/trunk/Doc/lib/libwebbrowser.tex (original) +++ python/trunk/Doc/lib/libwebbrowser.tex Sun Apr 1 23:29:15 2007 @@ -154,19 +154,19 @@ Browser controllers provide two methods which parallel two of the module-level convenience functions: -\begin{methoddesc}{open}{url\optional{, new\optional{, autoraise=1}}} +\begin{methoddesc}[controller]{open}{url\optional{, new\optional{, autoraise=1}}} Display \var{url} using the browser handled by this controller. If \var{new} is 1, a new browser window is opened if possible. If \var{new} is 2, a new browser page ("tab") is opened if possible. \end{methoddesc} -\begin{methoddesc}{open_new}{url} +\begin{methoddesc}[controller]{open_new}{url} Open \var{url} in a new window of the browser handled by this controller, if possible, otherwise, open \var{url} in the only browser window. Alias \function{open_new}. \end{methoddesc} -\begin{methoddesc}{open_new_tab}{url} +\begin{methoddesc}[controller]{open_new_tab}{url} Open \var{url} in a new page ("tab") of the browser handled by this controller, if possible, otherwise equivalent to \function{open_new}. \versionadded{2.5} Modified: python/trunk/Doc/lib/libwinreg.tex ============================================================================== --- python/trunk/Doc/lib/libwinreg.tex (original) +++ python/trunk/Doc/lib/libwinreg.tex Sun Apr 1 23:29:15 2007 @@ -393,14 +393,14 @@ \method{Detach()} method to return the integer handle, and also disconnect the Windows handle from the handle object. -\begin{methoddesc}{Close}{} +\begin{methoddesc}[PyHKEY]{Close}{} Closes the underlying Windows handle. If the handle is already closed, no error is raised. \end{methoddesc} -\begin{methoddesc}{Detach}{} +\begin{methoddesc}[PyHKEY]{Detach}{} Detaches the Windows handle from the handle object. The result is an integer (or long on 64 bit Windows) that holds Modified: python/trunk/Doc/lib/libzlib.tex ============================================================================== --- python/trunk/Doc/lib/libzlib.tex (original) +++ python/trunk/Doc/lib/libzlib.tex Sun Apr 1 23:29:15 2007 @@ -131,7 +131,7 @@ Decompression objects support the following methods, and two attributes: -\begin{memberdesc}{unused_data} +\begin{memberdesc}[Decompress]{unused_data} A string which contains any bytes past the end of the compressed data. That is, this remains \code{""} until the last byte that contains compression data is available. If the whole string turned out to @@ -145,7 +145,7 @@ \member{unused_data} attribute is no longer the empty string. \end{memberdesc} -\begin{memberdesc}{unconsumed_tail} +\begin{memberdesc}[Decompress]{unconsumed_tail} A string that contains any data that was not consumed by the last \method{decompress} call because it exceeded the limit for the uncompressed data buffer. This data has not yet been seen by the zlib Modified: python/trunk/Doc/mac/libframework.tex ============================================================================== --- python/trunk/Doc/mac/libframework.tex (original) +++ python/trunk/Doc/mac/libframework.tex Sun Apr 1 23:29:15 2007 @@ -218,7 +218,7 @@ An update event for the window was received. Redraw the window. \end{methoddesc} -\begin{methoddesc}{do_activate}{activate, event} +\begin{methoddesc}[Window]{do_activate}{activate, event} The window was activated (\code{\var{activate} == 1}) or deactivated (\code{\var{activate} == 0}). Handle things like focus highlighting, etc. From python-checkins at python.org Sun Apr 1 23:39:53 2007 From: python-checkins at python.org (georg.brandl) Date: Sun, 1 Apr 2007 23:39:53 +0200 (CEST) Subject: [Python-checkins] r54650 - python/trunk/Doc/lib/libre.tex Message-ID: <20070401213953.0CED41E4007@bag.python.org> Author: georg.brandl Date: Sun Apr 1 23:39:52 2007 New Revision: 54650 Modified: python/trunk/Doc/lib/libre.tex Log: Another fix. Modified: python/trunk/Doc/lib/libre.tex ============================================================================== --- python/trunk/Doc/lib/libre.tex (original) +++ python/trunk/Doc/lib/libre.tex Sun Apr 1 23:39:52 2007 @@ -812,7 +812,7 @@ \end{methoddesc} \begin{methoddesc}[MatchObject]{start}{\optional{group}} -\methodline{end}{\optional{group}} +\methodline[MatchObject]{end}{\optional{group}} Return the indices of the start and end of the substring matched by \var{group}; \var{group} defaults to zero (meaning the whole matched substring). From buildbot at python.org Sun Apr 1 23:43:46 2007 From: buildbot at python.org (buildbot at python.org) Date: Sun, 01 Apr 2007 21:43:46 +0000 Subject: [Python-checkins] buildbot warnings in x86 Ubuntu edgy (icc) trunk Message-ID: <20070401214346.806F41E4007@bag.python.org> The Buildbot has detected a new failure of x86 Ubuntu edgy (icc) trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520Ubuntu%2520edgy%2520%2528icc%2529%2520trunk/builds/1216 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon Build had warnings: warnings test Excerpt from the test logfile: Traceback (most recent call last): File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') Traceback (most recent call last): File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 1 test failed: test_strptime ====================================================================== ERROR: test_TimeRE_recreation (test.test_strptime.CacheTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/test/test_strptime.py", line 518, in test_TimeRE_recreation locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8')) File "/home/buildbot/Buildbot/trunk.baxter-ubuntu/build/Lib/locale.py", line 476, in setlocale return _setlocale(category, locale) Error: unsupported locale setting sincerely, -The Buildbot From python-checkins at python.org Mon Apr 2 00:39:26 2007 From: python-checkins at python.org (georg.brandl) Date: Mon, 2 Apr 2007 00:39:26 +0200 (CEST) Subject: [Python-checkins] r54651 - in python/trunk/Doc: lib/libcfgparser.tex lib/libcmd.tex lib/libcode.tex lib/libcollections.tex lib/libcookielib.tex lib/libdatetime.tex lib/libdocxmlrpc.tex lib/libftplib.tex lib/libfuncs.tex lib/libhotshot.tex lib/libhtmllib.tex lib/libhttplib.tex lib/libimaplib.tex lib/libmailbox.tex lib/libmimetools.tex lib/libmimetypes.tex lib/libmimewriter.tex lib/libmsilib.tex lib/libmultifile.tex lib/libmutex.tex lib/libnetrc.tex lib/libnntplib.tex lib/libpipes.tex lib/libpopen2.tex lib/libpoplib.tex lib/libpprint.tex lib/libqueue.tex lib/librepr.tex lib/librexec.tex lib/librfc822.tex lib/libsched.tex lib/libshlex.tex lib/libsimplexmlrpc.tex lib/libsmtplib.tex lib/libsubprocess.tex lib/libtelnetlib.tex lib/libthreading.tex lib/libturtle.tex lib/libunittest.tex lib/liburllib2.tex lib/libxmlrpclib.tex mac/libmacic.tex Message-ID: <20070401223926.6378A1E4007@bag.python.org> Author: georg.brandl Date: Mon Apr 2 00:39:10 2007 New Revision: 54651 Modified: python/trunk/Doc/lib/libcfgparser.tex python/trunk/Doc/lib/libcmd.tex python/trunk/Doc/lib/libcode.tex python/trunk/Doc/lib/libcollections.tex python/trunk/Doc/lib/libcookielib.tex python/trunk/Doc/lib/libdatetime.tex python/trunk/Doc/lib/libdocxmlrpc.tex python/trunk/Doc/lib/libftplib.tex python/trunk/Doc/lib/libfuncs.tex python/trunk/Doc/lib/libhotshot.tex python/trunk/Doc/lib/libhtmllib.tex python/trunk/Doc/lib/libhttplib.tex python/trunk/Doc/lib/libimaplib.tex python/trunk/Doc/lib/libmailbox.tex python/trunk/Doc/lib/libmimetools.tex python/trunk/Doc/lib/libmimetypes.tex python/trunk/Doc/lib/libmimewriter.tex python/trunk/Doc/lib/libmsilib.tex python/trunk/Doc/lib/libmultifile.tex python/trunk/Doc/lib/libmutex.tex python/trunk/Doc/lib/libnetrc.tex python/trunk/Doc/lib/libnntplib.tex python/trunk/Doc/lib/libpipes.tex python/trunk/Doc/lib/libpopen2.tex python/trunk/Doc/lib/libpoplib.tex python/trunk/Doc/lib/libpprint.tex python/trunk/Doc/lib/libqueue.tex python/trunk/Doc/lib/librepr.tex python/trunk/Doc/lib/librexec.tex python/trunk/Doc/lib/librfc822.tex python/trunk/Doc/lib/libsched.tex python/trunk/Doc/lib/libshlex.tex python/trunk/Doc/lib/libsimplexmlrpc.tex python/trunk/Doc/lib/libsmtplib.tex python/trunk/Doc/lib/libsubprocess.tex python/trunk/Doc/lib/libtelnetlib.tex python/trunk/Doc/lib/libthreading.tex python/trunk/Doc/lib/libturtle.tex python/trunk/Doc/lib/libunittest.tex python/trunk/Doc/lib/liburllib2.tex python/trunk/Doc/lib/libxmlrpclib.tex python/trunk/Doc/mac/libmacic.tex Log: Lots of explicit class names for method and member descs. Modified: python/trunk/Doc/lib/libcfgparser.tex ============================================================================== --- python/trunk/Doc/lib/libcfgparser.tex (original) +++ python/trunk/Doc/lib/libcfgparser.tex Mon Apr 2 00:39:10 2007 @@ -155,37 +155,37 @@ \class{RawConfigParser} instances have the following methods: -\begin{methoddesc}{defaults}{} +\begin{methoddesc}[RawConfigParser]{defaults}{} Return a dictionary containing the instance-wide defaults. \end{methoddesc} -\begin{methoddesc}{sections}{} +\begin{methoddesc}[RawConfigParser]{sections}{} Return a list of the sections available; \code{DEFAULT} is not included in the list. \end{methoddesc} -\begin{methoddesc}{add_section}{section} +\begin{methoddesc}[RawConfigParser]{add_section}{section} Add a section named \var{section} to the instance. If a section by the given name already exists, \exception{DuplicateSectionError} is raised. \end{methoddesc} -\begin{methoddesc}{has_section}{section} +\begin{methoddesc}[RawConfigParser]{has_section}{section} Indicates whether the named section is present in the configuration. The \code{DEFAULT} section is not acknowledged. \end{methoddesc} -\begin{methoddesc}{options}{section} +\begin{methoddesc}[RawConfigParser]{options}{section} Returns a list of options available in the specified \var{section}. \end{methoddesc} -\begin{methoddesc}{has_option}{section, option} +\begin{methoddesc}[RawConfigParser]{has_option}{section, option} If the given section exists, and contains the given option, return \constant{True}; otherwise return \constant{False}. \versionadded{1.6} \end{methoddesc} -\begin{methoddesc}{read}{filenames} +\begin{methoddesc}[RawConfigParser]{read}{filenames} Attempt to read and parse a list of filenames, returning a list of filenames which were successfully parsed. If \var{filenames} is a string or Unicode string, it is treated as a single filename. @@ -210,28 +210,28 @@ \versionchanged[Returns list of successfully parsed filenames]{2.4} \end{methoddesc} -\begin{methoddesc}{readfp}{fp\optional{, filename}} +\begin{methoddesc}[RawConfigParser]{readfp}{fp\optional{, filename}} Read and parse configuration data from the file or file-like object in \var{fp} (only the \method{readline()} method is used). If \var{filename} is omitted and \var{fp} has a \member{name} attribute, that is used for \var{filename}; the default is \samp{}. \end{methoddesc} -\begin{methoddesc}{get}{section, option} +\begin{methoddesc}[RawConfigParser]{get}{section, option} Get an \var{option} value for the named \var{section}. \end{methoddesc} -\begin{methoddesc}{getint}{section, option} +\begin{methoddesc}[RawConfigParser]{getint}{section, option} A convenience method which coerces the \var{option} in the specified \var{section} to an integer. \end{methoddesc} -\begin{methoddesc}{getfloat}{section, option} +\begin{methoddesc}[RawConfigParser]{getfloat}{section, option} A convenience method which coerces the \var{option} in the specified \var{section} to a floating point number. \end{methoddesc} -\begin{methoddesc}{getboolean}{section, option} +\begin{methoddesc}[RawConfigParser]{getboolean}{section, option} A convenience method which coerces the \var{option} in the specified \var{section} to a Boolean value. Note that the accepted values for the option are \code{"1"}, \code{"yes"}, \code{"true"}, and \code{"on"}, @@ -241,12 +241,12 @@ cause it to raise \exception{ValueError}. \end{methoddesc} -\begin{methoddesc}{items}{section} +\begin{methoddesc}[RawConfigParser]{items}{section} Return a list of \code{(\var{name}, \var{value})} pairs for each option in the given \var{section}. \end{methoddesc} -\begin{methoddesc}{set}{section, option, value} +\begin{methoddesc}[RawConfigParser]{set}{section, option, value} If the given section exists, set the given option to the specified value; otherwise raise \exception{NoSectionError}. While it is possible to use \class{RawConfigParser} (or \class{ConfigParser} with @@ -256,14 +256,14 @@ \versionadded{1.6} \end{methoddesc} -\begin{methoddesc}{write}{fileobject} +\begin{methoddesc}[RawConfigParser]{write}{fileobject} Write a representation of the configuration to the specified file object. This representation can be parsed by a future \method{read()} call. \versionadded{1.6} \end{methoddesc} -\begin{methoddesc}{remove_option}{section, option} +\begin{methoddesc}[RawConfigParser]{remove_option}{section, option} Remove the specified \var{option} from the specified \var{section}. If the section does not exist, raise \exception{NoSectionError}. If the option existed to be removed, return \constant{True}; @@ -271,13 +271,13 @@ \versionadded{1.6} \end{methoddesc} -\begin{methoddesc}{remove_section}{section} +\begin{methoddesc}[RawConfigParser]{remove_section}{section} Remove the specified \var{section} from the configuration. If the section in fact existed, return \code{True}. Otherwise return \code{False}. \end{methoddesc} -\begin{methoddesc}{optionxform}{option} +\begin{methoddesc}[RawConfigParser]{optionxform}{option} Transforms the option name \var{option} as found in an input file or as passed in by client code to the form that should be used in the internal structures. The default implementation returns a lower-case @@ -293,14 +293,14 @@ The \class{ConfigParser} class extends some methods of the \class{RawConfigParser} interface, adding some optional arguments. -\begin{methoddesc}{get}{section, option\optional{, raw\optional{, vars}}} +\begin{methoddesc}[ConfigParser]{get}{section, option\optional{, raw\optional{, vars}}} Get an \var{option} value for the named \var{section}. All the \character{\%} interpolations are expanded in the return values, based on the defaults passed into the constructor, as well as the options \var{vars} provided, unless the \var{raw} argument is true. \end{methoddesc} -\begin{methoddesc}{items}{section\optional{, raw\optional{, vars}}} +\begin{methoddesc}[ConfigParser]{items}{section\optional{, raw\optional{, vars}}} Return a list of \code{(\var{name}, \var{value})} pairs for each option in the given \var{section}. Optional arguments have the same meaning as for the \method{get()} method. @@ -313,7 +313,7 @@ The \class{SafeConfigParser} class implements the same extended interface as \class{ConfigParser}, with the following addition: -\begin{methoddesc}{set}{section, option, value} +\begin{methoddesc}[SafeConfigParser]{set}{section, option, value} If the given section exists, set the given option to the specified value; otherwise raise \exception{NoSectionError}. \var{value} must be a string (\class{str} or \class{unicode}); if not, Modified: python/trunk/Doc/lib/libcmd.tex ============================================================================== --- python/trunk/Doc/lib/libcmd.tex (original) +++ python/trunk/Doc/lib/libcmd.tex Mon Apr 2 00:39:10 2007 @@ -37,7 +37,7 @@ A \class{Cmd} instance has the following methods: -\begin{methoddesc}{cmdloop}{\optional{intro}} +\begin{methoddesc}[Cmd]{cmdloop}{\optional{intro}} Repeatedly issue a prompt, accept input, parse an initial prefix off the received input, and dispatch to action methods, passing them the remainder of the line as argument. @@ -82,7 +82,7 @@ any undocumented commands. \end{methoddesc} -\begin{methoddesc}{onecmd}{str} +\begin{methoddesc}[Cmd]{onecmd}{str} Interpret the argument as though it had been typed in response to the prompt. This may be overridden, but should not normally need to be; see the \method{precmd()} and \method{postcmd()} methods for useful @@ -93,25 +93,25 @@ \method{default()} method is returned. \end{methoddesc} -\begin{methoddesc}{emptyline}{} +\begin{methoddesc}[Cmd]{emptyline}{} Method called when an empty line is entered in response to the prompt. If this method is not overridden, it repeats the last nonempty command entered. \end{methoddesc} -\begin{methoddesc}{default}{line} +\begin{methoddesc}[Cmd]{default}{line} Method called on an input line when the command prefix is not recognized. If this method is not overridden, it prints an error message and returns. \end{methoddesc} -\begin{methoddesc}{completedefault}{text, line, begidx, endidx} +\begin{methoddesc}[Cmd]{completedefault}{text, line, begidx, endidx} Method called to complete an input line when no command-specific \method{complete_*()} method is available. By default, it returns an empty list. \end{methoddesc} -\begin{methoddesc}{precmd}{line} +\begin{methoddesc}[Cmd]{precmd}{line} Hook method executed just before the command line \var{line} is interpreted, but after the input prompt is generated and issued. This method is a stub in \class{Cmd}; it exists to be overridden by @@ -121,7 +121,7 @@ unchanged. \end{methoddesc} -\begin{methoddesc}{postcmd}{stop, line} +\begin{methoddesc}[Cmd]{postcmd}{stop, line} Hook method executed just after a command dispatch is finished. This method is a stub in \class{Cmd}; it exists to be overridden by subclasses. \var{line} is the command line which was executed, and @@ -133,13 +133,13 @@ to continue. \end{methoddesc} -\begin{methoddesc}{preloop}{} +\begin{methoddesc}[Cmd]{preloop}{} Hook method executed once when \method{cmdloop()} is called. This method is a stub in \class{Cmd}; it exists to be overridden by subclasses. \end{methoddesc} -\begin{methoddesc}{postloop}{} +\begin{methoddesc}[Cmd]{postloop}{} Hook method executed once when \method{cmdloop()} is about to return. This method is a stub in \class{Cmd}; it exists to be overridden by subclasses. @@ -147,47 +147,47 @@ Instances of \class{Cmd} subclasses have some public instance variables: -\begin{memberdesc}{prompt} +\begin{memberdesc}[Cmd]{prompt} The prompt issued to solicit input. \end{memberdesc} -\begin{memberdesc}{identchars} +\begin{memberdesc}[Cmd]{identchars} The string of characters accepted for the command prefix. \end{memberdesc} -\begin{memberdesc}{lastcmd} +\begin{memberdesc}[Cmd]{lastcmd} The last nonempty command prefix seen. \end{memberdesc} -\begin{memberdesc}{intro} +\begin{memberdesc}[Cmd]{intro} A string to issue as an intro or banner. May be overridden by giving the \method{cmdloop()} method an argument. \end{memberdesc} -\begin{memberdesc}{doc_header} +\begin{memberdesc}[Cmd]{doc_header} The header to issue if the help output has a section for documented commands. \end{memberdesc} -\begin{memberdesc}{misc_header} +\begin{memberdesc}[Cmd]{misc_header} The header to issue if the help output has a section for miscellaneous help topics (that is, there are \method{help_*()} methods without corresponding \method{do_*()} methods). \end{memberdesc} -\begin{memberdesc}{undoc_header} +\begin{memberdesc}[Cmd]{undoc_header} The header to issue if the help output has a section for undocumented commands (that is, there are \method{do_*()} methods without corresponding \method{help_*()} methods). \end{memberdesc} -\begin{memberdesc}{ruler} +\begin{memberdesc}[Cmd]{ruler} The character used to draw separator lines under the help-message headers. If empty, no ruler line is drawn. It defaults to \character{=}. \end{memberdesc} -\begin{memberdesc}{use_rawinput} +\begin{memberdesc}[Cmd]{use_rawinput} A flag, defaulting to true. If true, \method{cmdloop()} uses \function{raw_input()} to display a prompt and read the next command; if false, \method{sys.stdout.write()} and Modified: python/trunk/Doc/lib/libcode.tex ============================================================================== --- python/trunk/Doc/lib/libcode.tex (original) +++ python/trunk/Doc/lib/libcode.tex Mon Apr 2 00:39:10 2007 @@ -68,7 +68,7 @@ \subsection{Interactive Interpreter Objects \label{interpreter-objects}} -\begin{methoddesc}{runsource}{source\optional{, filename\optional{, symbol}}} +\begin{methoddesc}[InteractiveInterpreter]{runsource}{source\optional{, filename\optional{, symbol}}} Compile and run some source in the interpreter. Arguments are the same as for \function{compile_command()}; the default for \var{filename} is \code{''}, and for @@ -98,7 +98,7 @@ \code{sys.ps1} or \code{sys.ps2} to prompt the next line. \end{methoddesc} -\begin{methoddesc}{runcode}{code} +\begin{methoddesc}[InteractiveInterpreter]{runcode}{code} Execute a code object. When an exception occurs, \method{showtraceback()} is called to display a traceback. All exceptions are caught except @@ -109,7 +109,7 @@ should be prepared to deal with it. \end{methoddesc} -\begin{methoddesc}{showsyntaxerror}{\optional{filename}} +\begin{methoddesc}[InteractiveInterpreter]{showsyntaxerror}{\optional{filename}} Display the syntax error that just occurred. This does not display a stack trace because there isn't one for syntax errors. If \var{filename} is given, it is stuffed into the exception instead @@ -118,13 +118,13 @@ The output is written by the \method{write()} method. \end{methoddesc} -\begin{methoddesc}{showtraceback}{} +\begin{methoddesc}[InteractiveInterpreter]{showtraceback}{} Display the exception that just occurred. We remove the first stack item because it is within the interpreter object implementation. The output is written by the \method{write()} method. \end{methoddesc} -\begin{methoddesc}{write}{data} +\begin{methoddesc}[InteractiveInterpreter]{write}{data} Write a string to the standard error stream (\code{sys.stderr}). Derived classes should override this to provide the appropriate output handling as needed. @@ -138,7 +138,7 @@ \class{InteractiveInterpreter}, and so offers all the methods of the interpreter objects as well as the following additions. -\begin{methoddesc}{interact}{\optional{banner}} +\begin{methoddesc}[InteractiveConsole]{interact}{\optional{banner}} Closely emulate the interactive Python console. The optional banner argument specify the banner to print before the first interaction; by default it prints a banner similar to the one @@ -147,7 +147,7 @@ with the real interpreter -- since it's so close!). \end{methoddesc} -\begin{methoddesc}{push}{line} +\begin{methoddesc}[InteractiveConsole]{push}{line} Push a line of source text to the interpreter. The line should not have a trailing newline; it may have internal newlines. The line is appended to a buffer and the interpreter's @@ -160,11 +160,11 @@ \method{runsource()}). \end{methoddesc} -\begin{methoddesc}{resetbuffer}{} +\begin{methoddesc}[InteractiveConsole]{resetbuffer}{} Remove any unhandled source text from the input buffer. \end{methoddesc} -\begin{methoddesc}{raw_input}{\optional{prompt}} +\begin{methoddesc}[InteractiveConsole]{raw_input}{\optional{prompt}} Write a prompt and read a line. The returned line does not include the trailing newline. When the user enters the \EOF{} key sequence, \exception{EOFError} is raised. The base implementation uses the Modified: python/trunk/Doc/lib/libcollections.tex ============================================================================== --- python/trunk/Doc/lib/libcollections.tex (original) +++ python/trunk/Doc/lib/libcollections.tex Mon Apr 2 00:39:10 2007 @@ -221,7 +221,7 @@ \subsection{\class{defaultdict} objects \label{defaultdict-objects}} -\begin{funcdesc}{defaultdict}{\optional{default_factory\optional{, ...}}} +\begin{classdesc}{defaultdict}{\optional{default_factory\optional{, ...}}} Returns a new dictionary-like object. \class{defaultdict} is a subclass of the builtin \class{dict} class. It overrides one method and adds one writable instance variable. The remaining functionality is the same as @@ -233,7 +233,7 @@ passed to the \class{dict} constructor, including keyword arguments. \versionadded{2.5} -\end{funcdesc} +\end{classdesc} \class{defaultdict} objects support the following method in addition to the standard \class{dict} operations: @@ -256,11 +256,11 @@ \class{defaultdict} objects support the following instance variable: -\begin{datadesc}{default_factory} +\begin{memberdesc}{default_factory} This attribute is used by the \method{__missing__} method; it is initialized from the first argument to the constructor, if present, or to \code{None}, if absent. -\end{datadesc} +\end{memberdesc} \subsubsection{\class{defaultdict} Examples \label{defaultdict-examples}} Modified: python/trunk/Doc/lib/libcookielib.tex ============================================================================== --- python/trunk/Doc/lib/libcookielib.tex (original) +++ python/trunk/Doc/lib/libcookielib.tex Mon Apr 2 00:39:10 2007 @@ -292,12 +292,12 @@ \class{FileCookieJar} instances have the following public attributes: -\begin{memberdesc}{filename} +\begin{memberdesc}[FileCookieJar]{filename} Filename of default file in which to keep cookies. This attribute may be assigned to. \end{memberdesc} -\begin{memberdesc}{delayload} +\begin{memberdesc}[FileCookieJar]{delayload} If true, load cookies lazily from disk. This attribute should not be assigned to. This is only a hint, since this only affects performance, not behaviour (unless the cookies on disk are changing). @@ -400,13 +400,13 @@ attributes, indicating which protocols should be used, and how. All of these attributes may be assigned to. -\begin{memberdesc}{netscape} +\begin{memberdesc}[CookiePolicy]{netscape} Implement Netscape protocol. \end{memberdesc} -\begin{memberdesc}{rfc2965} +\begin{memberdesc}[CookiePolicy]{rfc2965} Implement RFC 2965 protocol. \end{memberdesc} -\begin{memberdesc}{hide_cookie2} +\begin{memberdesc}[CookiePolicy]{hide_cookie2} Don't add \mailheader{Cookie2} header to requests (the presence of this header indicates to the server that we understand RFC 2965 cookies). @@ -504,7 +504,7 @@ which are all initialised from the constructor arguments of the same name, and which may all be assigned to. -\begin{memberdesc}{rfc2109_as_netscape} +\begin{memberdesc}[DefaultCookiePolicy]{rfc2109_as_netscape} If true, request that the \class{CookieJar} instance downgrade RFC 2109 cookies (ie. cookies received in a \mailheader{Set-Cookie} header with a version cookie-attribute of 1) to Netscape cookies by setting @@ -517,7 +517,7 @@ General strictness switches: -\begin{memberdesc}{strict_domain} +\begin{memberdesc}[DefaultCookiePolicy]{strict_domain} Don't allow sites to set two-component domains with country-code top-level domains like \code{.co.uk}, \code{.gov.uk}, \code{.co.nz}.etc. This is far from perfect and isn't guaranteed to @@ -526,7 +526,7 @@ RFC 2965 protocol strictness switches: -\begin{memberdesc}{strict_rfc2965_unverifiable} +\begin{memberdesc}[DefaultCookiePolicy]{strict_rfc2965_unverifiable} Follow RFC 2965 rules on unverifiable transactions (usually, an unverifiable transaction is one resulting from a redirect or a request for an image hosted on another site). If this is false, cookies are @@ -535,19 +535,19 @@ Netscape protocol strictness switches: -\begin{memberdesc}{strict_ns_unverifiable} +\begin{memberdesc}[DefaultCookiePolicy]{strict_ns_unverifiable} apply RFC 2965 rules on unverifiable transactions even to Netscape cookies \end{memberdesc} -\begin{memberdesc}{strict_ns_domain} +\begin{memberdesc}[DefaultCookiePolicy]{strict_ns_domain} Flags indicating how strict to be with domain-matching rules for Netscape cookies. See below for acceptable values. \end{memberdesc} -\begin{memberdesc}{strict_ns_set_initial_dollar} +\begin{memberdesc}[DefaultCookiePolicy]{strict_ns_set_initial_dollar} Ignore cookies in Set-Cookie: headers that have names starting with \code{'\$'}. \end{memberdesc} -\begin{memberdesc}{strict_ns_set_path} +\begin{memberdesc}[DefaultCookiePolicy]{strict_ns_set_path} Don't allow setting cookies whose path doesn't path-match request URI. \end{memberdesc} @@ -556,30 +556,30 @@ \code{DomainStrictNoDots|DomainStrictNonDomain} means both flags are set). -\begin{memberdesc}{DomainStrictNoDots} +\begin{memberdesc}[DefaultCookiePolicy]{DomainStrictNoDots} When setting cookies, the 'host prefix' must not contain a dot (eg. \code{www.foo.bar.com} can't set a cookie for \code{.bar.com}, because \code{www.foo} contains a dot). \end{memberdesc} -\begin{memberdesc}{DomainStrictNonDomain} +\begin{memberdesc}[DefaultCookiePolicy]{DomainStrictNonDomain} Cookies that did not explicitly specify a \code{domain} cookie-attribute can only be returned to a domain equal to the domain that set the cookie (eg. \code{spam.example.com} won't be returned cookies from \code{example.com} that had no \code{domain} cookie-attribute). \end{memberdesc} -\begin{memberdesc}{DomainRFC2965Match} +\begin{memberdesc}[DefaultCookiePolicy]{DomainRFC2965Match} When setting cookies, require a full RFC 2965 domain-match. \end{memberdesc} The following attributes are provided for convenience, and are the most useful combinations of the above flags: -\begin{memberdesc}{DomainLiberal} +\begin{memberdesc}[DefaultCookiePolicy]{DomainLiberal} Equivalent to 0 (ie. all of the above Netscape domain strictness flags switched off). \end{memberdesc} -\begin{memberdesc}{DomainStrict} +\begin{memberdesc}[DefaultCookiePolicy]{DomainStrict} Equivalent to \code{DomainStrictNoDots|DomainStrictNonDomain}. \end{memberdesc} Modified: python/trunk/Doc/lib/libdatetime.tex ============================================================================== --- python/trunk/Doc/lib/libdatetime.tex (original) +++ python/trunk/Doc/lib/libdatetime.tex Mon Apr 2 00:39:10 2007 @@ -1154,7 +1154,7 @@ uses made of aware \module{datetime} objects. If in doubt, simply implement all of them. -\begin{methoddesc}{utcoffset}{self, dt} +\begin{methoddesc}[tzinfo]{utcoffset}{self, dt} Return offset of local time from UTC, in minutes east of UTC. If local time is west of UTC, this should be negative. Note that this is intended to be the total offset from UTC; for example, if a @@ -1178,7 +1178,7 @@ \exception{NotImplementedError}. \end{methoddesc} -\begin{methoddesc}{dst}{self, dt} +\begin{methoddesc}[tzinfo]{dst}{self, dt} Return the daylight saving time (DST) adjustment, in minutes east of UTC, or \code{None} if DST information isn't known. Return \code{timedelta(0)} if DST is not in effect. @@ -1237,7 +1237,7 @@ \exception{NotImplementedError}. \end{methoddesc} -\begin{methoddesc}{tzname}{self, dt} +\begin{methoddesc}[tzinfo]{tzname}{self, dt} Return the time zone name corresponding to the \class{datetime} object \var{dt}, as a string. Nothing about string names is defined by the @@ -1278,7 +1278,7 @@ There is one more \class{tzinfo} method that a subclass may wish to override: -\begin{methoddesc}{fromutc}{self, dt} +\begin{methoddesc}[tzinfo]{fromutc}{self, dt} This is called from the default \class{datetime.astimezone()} implementation. When called from that, \code{\var{dt}.tzinfo} is \var{self}, and \var{dt}'s date and time members are to be viewed as Modified: python/trunk/Doc/lib/libdocxmlrpc.tex ============================================================================== --- python/trunk/Doc/lib/libdocxmlrpc.tex (original) +++ python/trunk/Doc/lib/libdocxmlrpc.tex Mon Apr 2 00:39:10 2007 @@ -51,14 +51,14 @@ handled by generating pydoc-style HTML documentation. This allows a server to provide its own web-based documentation. -\begin{methoddesc}{set_server_title}{server_title} +\begin{methoddesc}[DocXMLRPCServer]{set_server_title}{server_title} Set the title used in the generated HTML documentation. This title will be used inside the HTML "title" element. \end{methoddesc} -\begin{methoddesc}{set_server_name}{server_name} +\begin{methoddesc}[DocXMLRPCServer]{set_server_name}{server_name} Set the name used in the generated HTML documentation. This name will appear at the top of the generated documentation inside a "h1" @@ -67,7 +67,7 @@ \end{methoddesc} -\begin{methoddesc}{set_server_documentation}{server_documentation} +\begin{methoddesc}[DocXMLRPCServer]{set_server_documentation}{server_documentation} Set the description used in the generated HTML documentation. This description will appear as a paragraph, below the server name, in the @@ -84,14 +84,14 @@ generating pydoc-style HTML documentation. This allows a server to provide its own web-based documentation. -\begin{methoddesc}{set_server_title}{server_title} +\begin{methoddesc}[DocCGIXMLRPCRequestHandler]{set_server_title}{server_title} Set the title used in the generated HTML documentation. This title will be used inside the HTML "title" element. \end{methoddesc} -\begin{methoddesc}{set_server_name}{server_name} +\begin{methoddesc}[DocCGIXMLRPCRequestHandler]{set_server_name}{server_name} Set the name used in the generated HTML documentation. This name will appear at the top of the generated documentation inside a "h1" @@ -100,7 +100,7 @@ \end{methoddesc} -\begin{methoddesc}{set_server_documentation}{server_documentation} +\begin{methoddesc}[DocCGIXMLRPCRequestHandler]{set_server_documentation}{server_documentation} Set the description used in the generated HTML documentation. This description will appear as a paragraph, below the server name, in the Modified: python/trunk/Doc/lib/libftplib.tex ============================================================================== --- python/trunk/Doc/lib/libftplib.tex (original) +++ python/trunk/Doc/lib/libftplib.tex Mon Apr 2 00:39:10 2007 @@ -95,7 +95,7 @@ \class{FTP} instances have the following methods: -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[FTP]{set_debuglevel}{level} Set the instance's debugging level. This controls the amount of debugging output printed. The default, \code{0}, produces no debugging output. A value of \code{1} produces a moderate amount of @@ -104,7 +104,7 @@ logging each line sent and received on the control connection. \end{methoddesc} -\begin{methoddesc}{connect}{host\optional{, port\optional{, timeout}}} +\begin{methoddesc}[FTP]{connect}{host\optional{, port\optional{, timeout}}} Connect to the given host and port. The default port number is \code{21}, as specified by the FTP protocol specification. It is rarely needed to specify a different port number. This function should be called only @@ -119,13 +119,13 @@ setting will be used. \end{methoddesc} -\begin{methoddesc}{getwelcome}{} +\begin{methoddesc}[FTP]{getwelcome}{} Return the welcome message sent by the server in reply to the initial connection. (This message sometimes contains disclaimers or help information that may be relevant to the user.) \end{methoddesc} -\begin{methoddesc}{login}{\optional{user\optional{, passwd\optional{, acct}}}} +\begin{methoddesc}[FTP]{login}{\optional{user\optional{, passwd\optional{, acct}}}} Log in as the given \var{user}. The \var{passwd} and \var{acct} parameters are optional and default to the empty string. If no \var{user} is specified, it defaults to \code{'anonymous'}. If @@ -137,23 +137,23 @@ client has logged in. \end{methoddesc} -\begin{methoddesc}{abort}{} +\begin{methoddesc}[FTP]{abort}{} Abort a file transfer that is in progress. Using this does not always work, but it's worth a try. \end{methoddesc} -\begin{methoddesc}{sendcmd}{command} +\begin{methoddesc}[FTP]{sendcmd}{command} Send a simple command string to the server and return the response string. \end{methoddesc} -\begin{methoddesc}{voidcmd}{command} +\begin{methoddesc}[FTP]{voidcmd}{command} Send a simple command string to the server and handle the response. Return nothing if a response code in the range 200--299 is received. Raise an exception otherwise. \end{methoddesc} -\begin{methoddesc}{retrbinary}{command, +\begin{methoddesc}[FTP]{retrbinary}{command, callback\optional{, maxblocksize\optional{, rest}}} Retrieve a file in binary transfer mode. \var{command} should be an appropriate \samp{RETR} command: \code{'RETR \var{filename}'}. @@ -166,7 +166,7 @@ same thing as in the \method{transfercmd()} method. \end{methoddesc} -\begin{methoddesc}{retrlines}{command\optional{, callback}} +\begin{methoddesc}[FTP]{retrlines}{command\optional{, callback}} Retrieve a file or directory listing in \ASCII{} transfer mode. \var{command} should be an appropriate \samp{RETR} command (see \method{retrbinary()}) or a \samp{LIST} command (usually just the string @@ -175,13 +175,13 @@ the line to \code{sys.stdout}. \end{methoddesc} -\begin{methoddesc}{set_pasv}{boolean} +\begin{methoddesc}[FTP]{set_pasv}{boolean} Enable ``passive'' mode if \var{boolean} is true, other disable passive mode. (In Python 2.0 and before, passive mode was off by default; in Python 2.1 and later, it is on by default.) \end{methoddesc} -\begin{methoddesc}{storbinary}{command, file\optional{, blocksize}} +\begin{methoddesc}[FTP]{storbinary}{command, file\optional{, blocksize}} Store a file in binary transfer mode. \var{command} should be an appropriate \samp{STOR} command: \code{"STOR \var{filename}"}. \var{file} is an open file object which is read until \EOF{} using its @@ -190,14 +190,14 @@ \versionchanged[default for \var{blocksize} added]{2.1} \end{methoddesc} -\begin{methoddesc}{storlines}{command, file} +\begin{methoddesc}[FTP]{storlines}{command, file} Store a file in \ASCII{} transfer mode. \var{command} should be an appropriate \samp{STOR} command (see \method{storbinary()}). Lines are read until \EOF{} from the open file object \var{file} using its \method{readline()} method to provide the data to be stored. \end{methoddesc} -\begin{methoddesc}{transfercmd}{cmd\optional{, rest}} +\begin{methoddesc}[FTP]{transfercmd}{cmd\optional{, rest}} Initiate a transfer over the data connection. If the transfer is active, send a \samp{EPRT} or \samp{PORT} command and the transfer command specified by \var{cmd}, and accept the connection. If the server is passive, @@ -219,7 +219,7 @@ simply call \method{transfercmd()} without a \var{rest} argument. \end{methoddesc} -\begin{methoddesc}{ntransfercmd}{cmd\optional{, rest}} +\begin{methoddesc}[FTP]{ntransfercmd}{cmd\optional{, rest}} Like \method{transfercmd()}, but returns a tuple of the data connection and the expected size of the data. If the expected size could not be computed, \code{None} will be returned as the expected @@ -227,14 +227,14 @@ \method{transfercmd()}. \end{methoddesc} -\begin{methoddesc}{nlst}{argument\optional{, \ldots}} +\begin{methoddesc}[FTP]{nlst}{argument\optional{, \ldots}} Return a list of files as returned by the \samp{NLST} command. The optional \var{argument} is a directory to list (default is the current server directory). Multiple arguments can be used to pass non-standard options to the \samp{NLST} command. \end{methoddesc} -\begin{methoddesc}{dir}{argument\optional{, \ldots}} +\begin{methoddesc}[FTP]{dir}{argument\optional{, \ldots}} Produce a directory listing as returned by the \samp{LIST} command, printing it to standard output. The optional \var{argument} is a directory to list (default is the current server directory). Multiple @@ -244,41 +244,41 @@ prints to \code{sys.stdout}. This method returns \code{None}. \end{methoddesc} -\begin{methoddesc}{rename}{fromname, toname} +\begin{methoddesc}[FTP]{rename}{fromname, toname} Rename file \var{fromname} on the server to \var{toname}. \end{methoddesc} -\begin{methoddesc}{delete}{filename} +\begin{methoddesc}[FTP]{delete}{filename} Remove the file named \var{filename} from the server. If successful, returns the text of the response, otherwise raises \exception{error_perm} on permission errors or \exception{error_reply} on other errors. \end{methoddesc} -\begin{methoddesc}{cwd}{pathname} +\begin{methoddesc}[FTP]{cwd}{pathname} Set the current directory on the server. \end{methoddesc} -\begin{methoddesc}{mkd}{pathname} +\begin{methoddesc}[FTP]{mkd}{pathname} Create a new directory on the server. \end{methoddesc} -\begin{methoddesc}{pwd}{} +\begin{methoddesc}[FTP]{pwd}{} Return the pathname of the current directory on the server. \end{methoddesc} -\begin{methoddesc}{rmd}{dirname} +\begin{methoddesc}[FTP]{rmd}{dirname} Remove the directory named \var{dirname} on the server. \end{methoddesc} -\begin{methoddesc}{size}{filename} +\begin{methoddesc}[FTP]{size}{filename} Request the size of the file named \var{filename} on the server. On success, the size of the file is returned as an integer, otherwise \code{None} is returned. Note that the \samp{SIZE} command is not standardized, but is supported by many common server implementations. \end{methoddesc} -\begin{methoddesc}{quit}{} +\begin{methoddesc}[FTP]{quit}{} Send a \samp{QUIT} command to the server and close the connection. This is the ``polite'' way to close a connection, but it may raise an exception of the server reponds with an error to the @@ -287,7 +287,7 @@ calls (see below). \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[FTP]{close}{} Close the connection unilaterally. This should not be applied to an already closed connection such as after a successful call to \method{quit()}. After this call the \class{FTP} instance should not Modified: python/trunk/Doc/lib/libfuncs.tex ============================================================================== --- python/trunk/Doc/lib/libfuncs.tex (original) +++ python/trunk/Doc/lib/libfuncs.tex Mon Apr 2 00:39:10 2007 @@ -1166,7 +1166,7 @@ as detailed below. \end{funcdesc} -\begin{funcdesc}{type}{name, bases, dict} +\begin{funcdescni}{type}{name, bases, dict} Return a new type object. This is essentially a dynamic form of the \keyword{class} statement. The \var{name} string is the class name and becomes the \member{__name__} attribute; the \var{bases} tuple @@ -1183,7 +1183,7 @@ >>> X = type('X', (object,), dict(a=1)) \end{verbatim} \versionadded{2.2} -\end{funcdesc} +\end{funcdescni} \begin{funcdesc}{unichr}{i} Return the Unicode string of one character whose Unicode code is the Modified: python/trunk/Doc/lib/libhotshot.tex ============================================================================== --- python/trunk/Doc/lib/libhotshot.tex (original) +++ python/trunk/Doc/lib/libhotshot.tex Mon Apr 2 00:39:10 2007 @@ -48,25 +48,25 @@ Profile objects have the following methods: -\begin{methoddesc}{addinfo}{key, value} +\begin{methoddesc}[Profile]{addinfo}{key, value} Add an arbitrary labelled value to the profile output. \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[Profile]{close}{} Close the logfile and terminate the profiler. \end{methoddesc} -\begin{methoddesc}{fileno}{} +\begin{methoddesc}[Profile]{fileno}{} Return the file descriptor of the profiler's log file. \end{methoddesc} -\begin{methoddesc}{run}{cmd} +\begin{methoddesc}[Profile]{run}{cmd} Profile an \keyword{exec}-compatible string in the script environment. The globals from the \refmodule[main]{__main__} module are used as both the globals and locals for the script. \end{methoddesc} -\begin{methoddesc}{runcall}{func, *args, **keywords} +\begin{methoddesc}[Profile]{runcall}{func, *args, **keywords} Profile a single call of a callable. Additional positional and keyword arguments may be passed along; the result of the call is returned, and exceptions are @@ -75,16 +75,16 @@ \end{methoddesc} -\begin{methoddesc}{runctx}{cmd, globals, locals} +\begin{methoddesc}[Profile]{runctx}{cmd, globals, locals} Evaluate an \keyword{exec}-compatible string in a specific environment. The string is compiled before profiling begins. \end{methoddesc} -\begin{methoddesc}{start}{} +\begin{methoddesc}[Profile]{start}{} Start the profiler. \end{methoddesc} -\begin{methoddesc}{stop}{} +\begin{methoddesc}[Profile]{stop}{} Stop the profiler. \end{methoddesc} Modified: python/trunk/Doc/lib/libhtmllib.tex ============================================================================== --- python/trunk/Doc/lib/libhtmllib.tex (original) +++ python/trunk/Doc/lib/libhtmllib.tex Mon Apr 2 00:39:10 2007 @@ -96,11 +96,11 @@ In addition to tag methods, the \class{HTMLParser} class provides some additional methods and instance variables for use within tag methods. -\begin{memberdesc}{formatter} +\begin{memberdesc}[HTMLParser]{formatter} This is the formatter instance associated with the parser. \end{memberdesc} -\begin{memberdesc}{nofill} +\begin{memberdesc}[HTMLParser]{nofill} Boolean flag which should be true when whitespace should not be collapsed, or false when it should be. In general, this should only be true when character data is to be treated as ``preformatted'' text, @@ -109,7 +109,7 @@ \end{memberdesc} -\begin{methoddesc}{anchor_bgn}{href, name, type} +\begin{methoddesc}[HTMLParser]{anchor_bgn}{href, name, type} This method is called at the start of an anchor region. The arguments correspond to the attributes of the \code{} tag with the same names. The default implementation maintains a list of hyperlinks @@ -118,27 +118,27 @@ \member{anchorlist}. \end{methoddesc} -\begin{methoddesc}{anchor_end}{} +\begin{methoddesc}[HTMLParser]{anchor_end}{} This method is called at the end of an anchor region. The default implementation adds a textual footnote marker using an index into the list of hyperlinks created by \method{anchor_bgn()}. \end{methoddesc} -\begin{methoddesc}{handle_image}{source, alt\optional{, ismap\optional{, +\begin{methoddesc}[HTMLParser]{handle_image}{source, alt\optional{, ismap\optional{, align\optional{, width\optional{, height}}}}} This method is called to handle images. The default implementation simply passes the \var{alt} value to the \method{handle_data()} method. \end{methoddesc} -\begin{methoddesc}{save_bgn}{} +\begin{methoddesc}[HTMLParser]{save_bgn}{} Begins saving character data in a buffer instead of sending it to the formatter object. Retrieve the stored data via \method{save_end()}. Use of the \method{save_bgn()} / \method{save_end()} pair may not be nested. \end{methoddesc} -\begin{methoddesc}{save_end}{} +\begin{methoddesc}[HTMLParser]{save_end}{} Ends buffering character data and returns all data saved since the preceding call to \method{save_bgn()}. If the \member{nofill} flag is false, whitespace is collapsed to single spaces. A call to this Modified: python/trunk/Doc/lib/libhttplib.tex ============================================================================== --- python/trunk/Doc/lib/libhttplib.tex (original) +++ python/trunk/Doc/lib/libhttplib.tex Mon Apr 2 00:39:10 2007 @@ -309,7 +309,7 @@ \class{HTTPConnection} instances have the following methods: -\begin{methoddesc}{request}{method, url\optional{, body\optional{, headers}}} +\begin{methoddesc}[HTTPConnection]{request}{method, url\optional{, body\optional{, headers}}} This will send a request to the server using the HTTP request method \var{method} and the selector \var{url}. If the \var{body} argument is present, it should be a string of data to send after the headers are finished. @@ -323,24 +323,24 @@ \versionchanged[\var{body} can be a file object]{2.6} \end{methoddesc} -\begin{methoddesc}{getresponse}{} +\begin{methoddesc}[HTTPConnection]{getresponse}{} Should be called after a request is sent to get the response from the server. Returns an \class{HTTPResponse} instance. \note{Note that you must have read the whole response before you can send a new request to the server.} \end{methoddesc} -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[HTTPConnection]{set_debuglevel}{level} Set the debugging level (the amount of debugging output printed). The default debug level is \code{0}, meaning no debugging output is printed. \end{methoddesc} -\begin{methoddesc}{connect}{} +\begin{methoddesc}[HTTPConnection]{connect}{} Connect to the server specified when the object was created. \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[HTTPConnection]{close}{} Close the connection to the server. \end{methoddesc} @@ -348,7 +348,7 @@ you can also send your request step by step, by using the four functions below. -\begin{methoddesc}{putrequest}{request, selector\optional{, +\begin{methoddesc}[HTTPConnection]{putrequest}{request, selector\optional{, skip\_host\optional{, skip_accept_encoding}}} This should be the first call after the connection to the server has been made. It sends a line to the server consisting of the @@ -360,18 +360,18 @@ \versionchanged[\var{skip_accept_encoding} argument added]{2.4} \end{methoddesc} -\begin{methoddesc}{putheader}{header, argument\optional{, ...}} +\begin{methoddesc}[HTTPConnection]{putheader}{header, argument\optional{, ...}} Send an \rfc{822}-style header to the server. It sends a line to the server consisting of the header, a colon and a space, and the first argument. If more arguments are given, continuation lines are sent, each consisting of a tab and an argument. \end{methoddesc} -\begin{methoddesc}{endheaders}{} +\begin{methoddesc}[HTTPConnection]{endheaders}{} Send a blank line to the server, signalling the end of the headers. \end{methoddesc} -\begin{methoddesc}{send}{data} +\begin{methoddesc}[HTTPConnection]{send}{data} Send data to the server. This should be used directly only after the \method{endheaders()} method has been called and before \method{getresponse()} is called. @@ -381,34 +381,34 @@ \class{HTTPResponse} instances have the following methods and attributes: -\begin{methoddesc}{read}{\optional{amt}} +\begin{methoddesc}[HTTPResponse]{read}{\optional{amt}} Reads and returns the response body, or up to the next \var{amt} bytes. \end{methoddesc} -\begin{methoddesc}{getheader}{name\optional{, default}} +\begin{methoddesc}[HTTPResponse]{getheader}{name\optional{, default}} Get the contents of the header \var{name}, or \var{default} if there is no matching header. \end{methoddesc} -\begin{methoddesc}{getheaders}{} +\begin{methoddesc}[HTTPResponse]{getheaders}{} Return a list of (header, value) tuples. \versionadded{2.4} \end{methoddesc} -\begin{datadesc}{msg} +\begin{memberdesc}[HTTPResponse]{msg} A \class{mimetools.Message} instance containing the response headers. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{version} +\begin{memberdesc}[HTTPResponse]{version} HTTP protocol version used by server. 10 for HTTP/1.0, 11 for HTTP/1.1. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{status} +\begin{memberdesc}[HTTPResponse]{status} Status code returned by server. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{reason} +\begin{memberdesc}[HTTPResponse]{reason} Reason phrase returned by server. -\end{datadesc} +\end{memberdesc} \subsection{Examples \label{httplib-examples}} Modified: python/trunk/Doc/lib/libimaplib.tex ============================================================================== --- python/trunk/Doc/lib/libimaplib.tex (original) +++ python/trunk/Doc/lib/libimaplib.tex Mon Apr 2 00:39:10 2007 @@ -153,11 +153,11 @@ An \class{IMAP4} instance has the following methods: -\begin{methoddesc}{append}{mailbox, flags, date_time, message} +\begin{methoddesc}[IMAP4]{append}{mailbox, flags, date_time, message} Append \var{message} to named mailbox. \end{methoddesc} -\begin{methoddesc}{authenticate}{mechanism, authobject} +\begin{methoddesc}[IMAP4]{authenticate}{mechanism, authobject} Authenticate command --- requires response processing. \var{mechanism} specifies which authentication mechanism is to be @@ -176,115 +176,115 @@ be sent instead. \end{methoddesc} -\begin{methoddesc}{check}{} +\begin{methoddesc}[IMAP4]{check}{} Checkpoint mailbox on server. \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[IMAP4]{close}{} Close currently selected mailbox. Deleted messages are removed from writable mailbox. This is the recommended command before \samp{LOGOUT}. \end{methoddesc} -\begin{methoddesc}{copy}{message_set, new_mailbox} +\begin{methoddesc}[IMAP4]{copy}{message_set, new_mailbox} Copy \var{message_set} messages onto end of \var{new_mailbox}. \end{methoddesc} -\begin{methoddesc}{create}{mailbox} +\begin{methoddesc}[IMAP4]{create}{mailbox} Create new mailbox named \var{mailbox}. \end{methoddesc} -\begin{methoddesc}{delete}{mailbox} +\begin{methoddesc}[IMAP4]{delete}{mailbox} Delete old mailbox named \var{mailbox}. \end{methoddesc} -\begin{methoddesc}{deleteacl}{mailbox, who} +\begin{methoddesc}[IMAP4]{deleteacl}{mailbox, who} Delete the ACLs (remove any rights) set for who on mailbox. \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{expunge}{} +\begin{methoddesc}[IMAP4]{expunge}{} Permanently remove deleted items from selected mailbox. Generates an \samp{EXPUNGE} response for each deleted message. Returned data contains a list of \samp{EXPUNGE} message numbers in order received. \end{methoddesc} -\begin{methoddesc}{fetch}{message_set, message_parts} +\begin{methoddesc}[IMAP4]{fetch}{message_set, message_parts} Fetch (parts of) messages. \var{message_parts} should be a string of message part names enclosed within parentheses, eg: \samp{"(UID BODY[TEXT])"}. Returned data are tuples of message part envelope and data. \end{methoddesc} -\begin{methoddesc}{getacl}{mailbox} +\begin{methoddesc}[IMAP4]{getacl}{mailbox} Get the \samp{ACL}s for \var{mailbox}. The method is non-standard, but is supported by the \samp{Cyrus} server. \end{methoddesc} -\begin{methoddesc}{getannotation}{mailbox, entry, attribute} +\begin{methoddesc}[IMAP4]{getannotation}{mailbox, entry, attribute} Retrieve the specified \samp{ANNOTATION}s for \var{mailbox}. The method is non-standard, but is supported by the \samp{Cyrus} server. \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}{getquota}{root} +\begin{methoddesc}[IMAP4]{getquota}{root} Get the \samp{quota} \var{root}'s resource usage and limits. This method is part of the IMAP4 QUOTA extension defined in rfc2087. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{getquotaroot}{mailbox} +\begin{methoddesc}[IMAP4]{getquotaroot}{mailbox} Get the list of \samp{quota} \samp{roots} for the named \var{mailbox}. This method is part of the IMAP4 QUOTA extension defined in rfc2087. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{list}{\optional{directory\optional{, pattern}}} +\begin{methoddesc}[IMAP4]{list}{\optional{directory\optional{, pattern}}} List mailbox names in \var{directory} matching \var{pattern}. \var{directory} defaults to the top-level mail folder, and \var{pattern} defaults to match anything. Returned data contains a list of \samp{LIST} responses. \end{methoddesc} -\begin{methoddesc}{login}{user, password} +\begin{methoddesc}[IMAP4]{login}{user, password} Identify the client using a plaintext password. The \var{password} will be quoted. \end{methoddesc} -\begin{methoddesc}{login_cram_md5}{user, password} +\begin{methoddesc}[IMAP4]{login_cram_md5}{user, password} Force use of \samp{CRAM-MD5} authentication when identifying the client to protect the password. Will only work if the server \samp{CAPABILITY} response includes the phrase \samp{AUTH=CRAM-MD5}. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{logout}{} +\begin{methoddesc}[IMAP4]{logout}{} Shutdown connection to server. Returns server \samp{BYE} response. \end{methoddesc} -\begin{methoddesc}{lsub}{\optional{directory\optional{, pattern}}} +\begin{methoddesc}[IMAP4]{lsub}{\optional{directory\optional{, pattern}}} List subscribed mailbox names in directory matching pattern. \var{directory} defaults to the top level directory and \var{pattern} defaults to match any mailbox. Returned data are tuples of message part envelope and data. \end{methoddesc} -\begin{methoddesc}{myrights}{mailbox} +\begin{methoddesc}[IMAP4]{myrights}{mailbox} Show my ACLs for a mailbox (i.e. the rights that I have on mailbox). \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{namespace}{} +\begin{methoddesc}[IMAP4]{namespace}{} Returns IMAP namespaces as defined in RFC2342. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{noop}{} +\begin{methoddesc}[IMAP4]{noop}{} Send \samp{NOOP} to server. \end{methoddesc} -\begin{methoddesc}{open}{host, port} +\begin{methoddesc}[IMAP4]{open}{host, port} Opens socket to \var{port} at \var{host}. The connection objects established by this method will be used in the \code{read}, \code{readline}, \code{send}, and @@ -292,42 +292,42 @@ You may override this method. \end{methoddesc} -\begin{methoddesc}{partial}{message_num, message_part, start, length} +\begin{methoddesc}[IMAP4]{partial}{message_num, message_part, start, length} Fetch truncated part of a message. Returned data is a tuple of message part envelope and data. \end{methoddesc} -\begin{methoddesc}{proxyauth}{user} +\begin{methoddesc}[IMAP4]{proxyauth}{user} Assume authentication as \var{user}. Allows an authorised administrator to proxy into any user's mailbox. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{read}{size} +\begin{methoddesc}[IMAP4]{read}{size} Reads \var{size} bytes from the remote server. You may override this method. \end{methoddesc} -\begin{methoddesc}{readline}{} +\begin{methoddesc}[IMAP4]{readline}{} Reads one line from the remote server. You may override this method. \end{methoddesc} -\begin{methoddesc}{recent}{} +\begin{methoddesc}[IMAP4]{recent}{} Prompt server for an update. Returned data is \code{None} if no new messages, else value of \samp{RECENT} response. \end{methoddesc} -\begin{methoddesc}{rename}{oldmailbox, newmailbox} +\begin{methoddesc}[IMAP4]{rename}{oldmailbox, newmailbox} Rename mailbox named \var{oldmailbox} to \var{newmailbox}. \end{methoddesc} -\begin{methoddesc}{response}{code} +\begin{methoddesc}[IMAP4]{response}{code} Return data for response \var{code} if received, or \code{None}. Returns the given code, instead of the usual type. \end{methoddesc} -\begin{methoddesc}{search}{charset, criterion\optional{, ...}} +\begin{methoddesc}[IMAP4]{search}{charset, criterion\optional{, ...}} Search mailbox for matching messages. \var{charset} may be \code{None}, in which case no \samp{CHARSET} will be specified in the request to the server. The IMAP protocol requires that at least one @@ -345,45 +345,45 @@ \end{verbatim} \end{methoddesc} -\begin{methoddesc}{select}{\optional{mailbox\optional{, readonly}}} +\begin{methoddesc}[IMAP4]{select}{\optional{mailbox\optional{, readonly}}} Select a mailbox. Returned data is the count of messages in \var{mailbox} (\samp{EXISTS} response). The default \var{mailbox} is \code{'INBOX'}. If the \var{readonly} flag is set, modifications to the mailbox are not allowed. \end{methoddesc} -\begin{methoddesc}{send}{data} +\begin{methoddesc}[IMAP4]{send}{data} Sends \code{data} to the remote server. You may override this method. \end{methoddesc} -\begin{methoddesc}{setacl}{mailbox, who, what} +\begin{methoddesc}[IMAP4]{setacl}{mailbox, who, what} Set an \samp{ACL} for \var{mailbox}. The method is non-standard, but is supported by the \samp{Cyrus} server. \end{methoddesc} -\begin{methoddesc}{setannotation}{mailbox, entry, attribute\optional{, ...}} +\begin{methoddesc}[IMAP4]{setannotation}{mailbox, entry, attribute\optional{, ...}} Set \samp{ANNOTATION}s for \var{mailbox}. The method is non-standard, but is supported by the \samp{Cyrus} server. \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}{setquota}{root, limits} +\begin{methoddesc}[IMAP4]{setquota}{root, limits} Set the \samp{quota} \var{root}'s resource \var{limits}. This method is part of the IMAP4 QUOTA extension defined in rfc2087. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{shutdown}{} +\begin{methoddesc}[IMAP4]{shutdown}{} Close connection established in \code{open}. You may override this method. \end{methoddesc} -\begin{methoddesc}{socket}{} +\begin{methoddesc}[IMAP4]{socket}{} Returns socket instance used to connect to server. \end{methoddesc} -\begin{methoddesc}{sort}{sort_criteria, charset, search_criterion\optional{, ...}} +\begin{methoddesc}[IMAP4]{sort}{sort_criteria, charset, search_criterion\optional{, ...}} The \code{sort} command is a variant of \code{search} with sorting semantics for the results. Returned data contains a space separated list of matching message numbers. @@ -402,11 +402,11 @@ This is an \samp{IMAP4rev1} extension command. \end{methoddesc} -\begin{methoddesc}{status}{mailbox, names} +\begin{methoddesc}[IMAP4]{status}{mailbox, names} Request named status conditions for \var{mailbox}. \end{methoddesc} -\begin{methoddesc}{store}{message_set, command, flag_list} +\begin{methoddesc}[IMAP4]{store}{message_set, command, flag_list} Alters flag dispositions for messages in mailbox. \var{command} is specified by section 6.4.6 of \rfc{2060} as being one of "FLAGS", "+FLAGS", or "-FLAGS", optionally with a suffix of ".SILENT". @@ -421,11 +421,11 @@ \end{verbatim} \end{methoddesc} -\begin{methoddesc}{subscribe}{mailbox} +\begin{methoddesc}[IMAP4]{subscribe}{mailbox} Subscribe to new mailbox. \end{methoddesc} -\begin{methoddesc}{thread}{threading_algorithm, charset, +\begin{methoddesc}[IMAP4]{thread}{threading_algorithm, charset, search_criterion\optional{, ...}} The \code{thread} command is a variant of \code{search} with threading semantics for the results. Returned data contains a space @@ -448,18 +448,18 @@ This is an \samp{IMAP4rev1} extension command. \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{uid}{command, arg\optional{, ...}} +\begin{methoddesc}[IMAP4]{uid}{command, arg\optional{, ...}} Execute command args with messages identified by UID, rather than message number. Returns response appropriate to command. At least one argument must be supplied; if none are provided, the server will return an error and an exception will be raised. \end{methoddesc} -\begin{methoddesc}{unsubscribe}{mailbox} +\begin{methoddesc}[IMAP4]{unsubscribe}{mailbox} Unsubscribe from old mailbox. \end{methoddesc} -\begin{methoddesc}{xatom}{name\optional{, arg\optional{, ...}}} +\begin{methoddesc}[IMAP4]{xatom}{name\optional{, arg\optional{, ...}}} Allow simple extension commands notified by server in \samp{CAPABILITY} response. \end{methoddesc} @@ -467,7 +467,7 @@ Instances of \class{IMAP4_SSL} have just one additional method: -\begin{methoddesc}{ssl}{} +\begin{methoddesc}[IMAP4_SSL]{ssl}{} Returns SSLObject instance used for the secure connection with the server. \end{methoddesc} @@ -475,12 +475,12 @@ The following attributes are defined on instances of \class{IMAP4}: -\begin{memberdesc}{PROTOCOL_VERSION} +\begin{memberdesc}[IMAP4]{PROTOCOL_VERSION} The most recent supported protocol in the \samp{CAPABILITY} response from the server. \end{memberdesc} -\begin{memberdesc}{debug} +\begin{memberdesc}[IMAP4]{debug} Integer value to control debugging output. The initialize value is taken from the module variable \code{Debug}. Values greater than three trace each command. Modified: python/trunk/Doc/lib/libmailbox.tex ============================================================================== --- python/trunk/Doc/lib/libmailbox.tex (original) +++ python/trunk/Doc/lib/libmailbox.tex Mon Apr 2 00:39:10 2007 @@ -1246,7 +1246,7 @@ Older mailbox objects support only iteration and provide a single public method: -\begin{methoddesc}{next}{} +\begin{methoddesc}[oldmailbox]{next}{} Return the next message in the mailbox, created with the optional \var{factory} argument passed into the mailbox object's constructor. By default this is an \class{rfc822.Message} object (see the \refmodule{rfc822} module). Depending Modified: python/trunk/Doc/lib/libmimetools.tex ============================================================================== --- python/trunk/Doc/lib/libmimetools.tex (original) +++ python/trunk/Doc/lib/libmimetools.tex Mon Apr 2 00:39:10 2007 @@ -76,7 +76,7 @@ The \class{Message} class defines the following methods in addition to the \class{rfc822.Message} methods: -\begin{methoddesc}{getplist}{} +\begin{methoddesc}[Message]{getplist}{} Return the parameter list of the \mailheader{Content-Type} header. This is a list of strings. For parameters of the form \samp{\var{key}=\var{value}}, \var{key} is converted to lower case but @@ -86,34 +86,34 @@ 'spam=2', 'Spam']}. \end{methoddesc} -\begin{methoddesc}{getparam}{name} +\begin{methoddesc}[Message]{getparam}{name} Return the \var{value} of the first parameter (as returned by \method{getplist()}) of the form \samp{\var{name}=\var{value}} for the given \var{name}. If \var{value} is surrounded by quotes of the form `\code{<}...\code{>}' or `\code{"}...\code{"}', these are removed. \end{methoddesc} -\begin{methoddesc}{getencoding}{} +\begin{methoddesc}[Message]{getencoding}{} Return the encoding specified in the \mailheader{Content-Transfer-Encoding} message header. If no such header exists, return \code{'7bit'}. The encoding is converted to lower case. \end{methoddesc} -\begin{methoddesc}{gettype}{} +\begin{methoddesc}[Message]{gettype}{} Return the message type (of the form \samp{\var{type}/\var{subtype}}) as specified in the \mailheader{Content-Type} header. If no such header exists, return \code{'text/plain'}. The type is converted to lower case. \end{methoddesc} -\begin{methoddesc}{getmaintype}{} +\begin{methoddesc}[Message]{getmaintype}{} Return the main type as specified in the \mailheader{Content-Type} header. If no such header exists, return \code{'text'}. The main type is converted to lower case. \end{methoddesc} -\begin{methoddesc}{getsubtype}{} +\begin{methoddesc}[Message]{getsubtype}{} Return the subtype as specified in the \mailheader{Content-Type} header. If no such header exists, return \code{'plain'}. The subtype is converted to lower case. Modified: python/trunk/Doc/lib/libmimetypes.tex ============================================================================== --- python/trunk/Doc/lib/libmimetypes.tex (original) +++ python/trunk/Doc/lib/libmimetypes.tex Mon Apr 2 00:39:10 2007 @@ -178,49 +178,49 @@ \class{MimeTypes} instances provide an interface which is very like that of the \refmodule{mimetypes} module. -\begin{datadesc}{suffix_map} +\begin{memberdesc}[MimeTypes]{suffix_map} Dictionary mapping suffixes to suffixes. This is used to allow recognition of encoded files for which the encoding and the type are indicated by the same extension. For example, the \file{.tgz} extension is mapped to \file{.tar.gz} to allow the encoding and type to be recognized separately. This is initially a copy of the global \code{suffix_map} defined in the module. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{encodings_map} +\begin{memberdesc}[MimeTypes]{encodings_map} Dictionary mapping filename extensions to encoding types. This is initially a copy of the global \code{encodings_map} defined in the module. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{types_map} +\begin{memberdesc}[MimeTypes]{types_map} Dictionary mapping filename extensions to MIME types. This is initially a copy of the global \code{types_map} defined in the module. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{common_types} +\begin{memberdesc}[MimeTypes]{common_types} Dictionary mapping filename extensions to non-standard, but commonly found MIME types. This is initially a copy of the global \code{common_types} defined in the module. -\end{datadesc} +\end{memberdesc} -\begin{methoddesc}{guess_extension}{type\optional{, strict}} +\begin{methoddesc}[MimeTypes]{guess_extension}{type\optional{, strict}} Similar to the \function{guess_extension()} function, using the tables stored as part of the object. \end{methoddesc} -\begin{methoddesc}{guess_type}{url\optional{, strict}} +\begin{methoddesc}[MimeTypes]{guess_type}{url\optional{, strict}} Similar to the \function{guess_type()} function, using the tables stored as part of the object. \end{methoddesc} -\begin{methoddesc}{read}{path} +\begin{methoddesc}[MimeTypes]{read}{path} Load MIME information from a file named \var{path}. This uses \method{readfp()} to parse the file. \end{methoddesc} -\begin{methoddesc}{readfp}{file} +\begin{methoddesc}[MimeTypes]{readfp}{file} Load MIME type information from an open file. The file must have the format of the standard \file{mime.types} files. \end{methoddesc} Modified: python/trunk/Doc/lib/libmimewriter.tex ============================================================================== --- python/trunk/Doc/lib/libmimewriter.tex (original) +++ python/trunk/Doc/lib/libmimewriter.tex Mon Apr 2 00:39:10 2007 @@ -31,7 +31,7 @@ \class{MimeWriter} instances have the following methods: -\begin{methoddesc}{addheader}{key, value\optional{, prefix}} +\begin{methoddesc}[MimeWriter]{addheader}{key, value\optional{, prefix}} Add a header line to the MIME message. The \var{key} is the name of the header, where the \var{value} obviously provides the value of the header. The optional argument \var{prefix} determines where the header @@ -39,14 +39,14 @@ the start. The default is to append. \end{methoddesc} -\begin{methoddesc}{flushheaders}{} +\begin{methoddesc}[MimeWriter]{flushheaders}{} Causes all headers accumulated so far to be written out (and forgotten). This is useful if you don't need a body part at all, e.g.\ for a subpart of type \mimetype{message/rfc822} that's (mis)used to store some header-like information. \end{methoddesc} -\begin{methoddesc}{startbody}{ctype\optional{, plist\optional{, prefix}}} +\begin{methoddesc}[MimeWriter]{startbody}{ctype\optional{, plist\optional{, prefix}}} Returns a file-like object which can be used to write to the body of the message. The content-type is set to the provided \var{ctype}, and the optional parameter \var{plist} provides @@ -55,8 +55,8 @@ insert at the start. \end{methoddesc} -\begin{methoddesc}{startmultipartbody}{subtype\optional{, - boundary\optional{, plist\optional{, prefix}}}} +\begin{methoddesc}[MimeWriter]{startmultipartbody}{subtype\optional{, + boundary\optional{, plist\optional{, prefix}}}} Returns a file-like object which can be used to write to the body of the message. Additionally, this method initializes the multi-part code, where \var{subtype} provides the multipart subtype, @@ -66,7 +66,7 @@ created using \method{nextpart()}. \end{methoddesc} -\begin{methoddesc}{nextpart}{} +\begin{methoddesc}[MimeWriter]{nextpart}{} Returns a new instance of \class{MimeWriter} which represents an individual part in a multipart message. This may be used to write the part as well as used for creating recursively complex multipart @@ -74,7 +74,7 @@ \method{startmultipartbody()} before using \method{nextpart()}. \end{methoddesc} -\begin{methoddesc}{lastpart}{} +\begin{methoddesc}[MimeWriter]{lastpart}{} This is used to designate the last part of a multipart message, and should \emph{always} be used when writing multipart messages. \end{methoddesc} Modified: python/trunk/Doc/lib/libmsilib.tex ============================================================================== --- python/trunk/Doc/lib/libmsilib.tex (original) +++ python/trunk/Doc/lib/libmsilib.tex Mon Apr 2 00:39:10 2007 @@ -121,17 +121,17 @@ \subsection{Database Objects\label{database-objects}} -\begin{methoddesc}{OpenView}{sql} +\begin{methoddesc}[Database]{OpenView}{sql} Return a view object, by calling \cfunction{MSIDatabaseOpenView}. \var{sql} is the SQL statement to execute. \end{methoddesc} -\begin{methoddesc}{Commit}{} +\begin{methoddesc}[Database]{Commit}{} Commit the changes pending in the current transaction, by calling \cfunction{MSIDatabaseCommit}. \end{methoddesc} -\begin{methoddesc}{GetSummaryInformation}{count} +\begin{methoddesc}[Database]{GetSummaryInformation}{count} Return a new summary information object, by calling \cfunction{MsiGetSummaryInformation}. \var{count} is the maximum number of updated values. @@ -145,24 +145,24 @@ \subsection{View Objects\label{view-objects}} -\begin{methoddesc}{Execute}{\optional{params=None}} +\begin{methoddesc}[View]{Execute}{\optional{params=None}} Execute the SQL query of the view, through \cfunction{MSIViewExecute}. \var{params} is an optional record describing actual values of the parameter tokens in the query. \end{methoddesc} -\begin{methoddesc}{GetColumnInfo}{kind} +\begin{methoddesc}[View]{GetColumnInfo}{kind} Return a record describing the columns of the view, through calling \cfunction{MsiViewGetColumnInfo}. \var{kind} can be either \code{MSICOLINFO_NAMES} or \code{MSICOLINFO_TYPES}. \end{methoddesc} -\begin{methoddesc}{Fetch}{} +\begin{methoddesc}[View]{Fetch}{} Return a result record of the query, through calling \cfunction{MsiViewFetch}. \end{methoddesc} -\begin{methoddesc}{Modify}{kind, data} +\begin{methoddesc}[View]{Modify}{kind, data} Modify the view, by calling \cfunction{MsiViewModify}. \var{kind} can be one of \code{MSIMODIFY_SEEK}, \code{MSIMODIFY_REFRESH}, \code{MSIMODIFY_INSERT}, \code{MSIMODIFY_UPDATE}, \code{MSIMODIFY_ASSIGN}, @@ -174,7 +174,7 @@ \var{data} must be a record describing the new data. \end{methoddesc} -\begin{methoddesc}{Close}{} +\begin{methoddesc}[View]{Close}{} Close the view, through \cfunction{MsiViewClose}. \end{methoddesc} @@ -188,7 +188,7 @@ \subsection{Summary Information Objects\label{summary-objects}} -\begin{methoddesc}{GetProperty}{field} +\begin{methoddesc}[SummaryInformation]{GetProperty}{field} Return a property of the summary, through \cfunction{MsiSummaryInfoGetProperty}. \var{field} is the name of the property, and can be one of the constants @@ -200,19 +200,19 @@ \code{PID_APPNAME}, or \code{PID_SECURITY}. \end{methoddesc} -\begin{methoddesc}{GetPropertyCount}{} +\begin{methoddesc}[SummaryInformation]{GetPropertyCount}{} Return the number of summary properties, through \cfunction{MsiSummaryInfoGetPropertyCount}. \end{methoddesc} -\begin{methoddesc}{SetProperty}{field, value} +\begin{methoddesc}[SummaryInformation]{SetProperty}{field, value} Set a property through \cfunction{MsiSummaryInfoSetProperty}. \var{field} can have the same values as in \method{GetProperty}, \var{value} is the new value of the property. Possible value types are integer and string. \end{methoddesc} -\begin{methoddesc}{Persist}{} +\begin{methoddesc}[SummaryInformation]{Persist}{} Write the modified properties to the summary information stream, using \cfunction{MsiSummaryInfoPersist}. \end{methoddesc} @@ -226,27 +226,27 @@ \subsection{Record Objects\label{record-objects}} -\begin{methoddesc}{GetFieldCount}{} +\begin{methoddesc}[Record]{GetFieldCount}{} Return the number of fields of the record, through \cfunction{MsiRecordGetFieldCount}. \end{methoddesc} -\begin{methoddesc}{SetString}{field, value} +\begin{methoddesc}[Record]{SetString}{field, value} Set \var{field} to \var{value} through \cfunction{MsiRecordSetString}. \var{field} must be an integer; \var{value} a string. \end{methoddesc} -\begin{methoddesc}{SetStream}{field, value} +\begin{methoddesc}[Record]{SetStream}{field, value} Set \var{field} to the contents of the file named \var{value}, through \cfunction{MsiRecordSetStream}. \var{field} must be an integer; \var{value} a string. \end{methoddesc} -\begin{methoddesc}{SetInteger}{field, value} +\begin{methoddesc}[Record]{SetInteger}{field, value} Set \var{field} to \var{value} through \cfunction{MsiRecordSetInteger}. Both \var{field} and \var{value} must be an integer. \end{methoddesc} -\begin{methoddesc}{ClearData}{} +\begin{methoddesc}[Record]{ClearData}{} Set all fields of the record to 0, through \cfunction{MsiRecordClearData}. \end{methoddesc} @@ -274,7 +274,7 @@ \var{name} is the name of the CAB file in the MSI file. \end{classdesc} -\begin{methoddesc}[CAB]{append}{full, logical} +\begin{methoddesc}[CAB]{append}{full, file, logical} Add the file with the pathname \var{full} to the CAB file, under the name \var{logical}. If there is already a file named \var{logical}, a new file name is created. @@ -283,7 +283,7 @@ new name of the file inside the CAB file. \end{methoddesc} -\begin{methoddesc}[CAB]{append}{database} +\begin{methoddesc}[CAB]{commit}{database} Generate a CAB file, add it as a stream to the MSI file, put it into the \code{Media} table, and remove the generated file from the disk. Modified: python/trunk/Doc/lib/libmultifile.tex ============================================================================== --- python/trunk/Doc/lib/libmultifile.tex (original) +++ python/trunk/Doc/lib/libmultifile.tex Mon Apr 2 00:39:10 2007 @@ -48,7 +48,7 @@ A \class{MultiFile} instance has the following methods: -\begin{methoddesc}{readline}{str} +\begin{methoddesc}[MultiFile]{readline}{str} Read a line. If the line is data (not a section-divider or end-marker or real EOF) return it. If the line matches the most-recently-stacked boundary, return \code{''} and set \code{self.last} to 1 or 0 according as @@ -58,33 +58,33 @@ all boundaries have been popped. \end{methoddesc} -\begin{methoddesc}{readlines}{str} +\begin{methoddesc}[MultiFile]{readlines}{str} Return all lines remaining in this part as a list of strings. \end{methoddesc} -\begin{methoddesc}{read}{} +\begin{methoddesc}[MultiFile]{read}{} Read all lines, up to the next section. Return them as a single (multiline) string. Note that this doesn't take a size argument! \end{methoddesc} -\begin{methoddesc}{seek}{pos\optional{, whence}} +\begin{methoddesc}[MultiFile]{seek}{pos\optional{, whence}} Seek. Seek indices are relative to the start of the current section. The \var{pos} and \var{whence} arguments are interpreted as for a file seek. \end{methoddesc} -\begin{methoddesc}{tell}{} +\begin{methoddesc}[MultiFile]{tell}{} Return the file position relative to the start of the current section. \end{methoddesc} -\begin{methoddesc}{next}{} +\begin{methoddesc}[MultiFile]{next}{} Skip lines to the next section (that is, read lines until a section-divider or end-marker has been consumed). Return true if there is such a section, false if an end-marker is seen. Re-enable the most-recently-pushed boundary. \end{methoddesc} -\begin{methoddesc}{is_data}{str} +\begin{methoddesc}[MultiFile]{is_data}{str} Return true if \var{str} is data and false if it might be a section boundary. As written, it tests for a prefix other than \code{'-}\code{-'} at start of line (which all MIME boundaries have) but it is declared so @@ -95,7 +95,7 @@ processing, not cause it to fail. \end{methoddesc} -\begin{methoddesc}{push}{str} +\begin{methoddesc}[MultiFile]{push}{str} Push a boundary string. When a decorated version of this boundary is found as an input line, it will be interpreted as a section-divider or end-marker (depending on the decoration, see \rfc{2045}). All subsequent @@ -108,12 +108,12 @@ boundary will raise an error. \end{methoddesc} -\begin{methoddesc}{pop}{} +\begin{methoddesc}[MultiFile]{pop}{} Pop a section boundary. This boundary will no longer be interpreted as EOF. \end{methoddesc} -\begin{methoddesc}{section_divider}{str} +\begin{methoddesc}[MultiFile]{section_divider}{str} Turn a boundary into a section-divider line. By default, this method prepends \code{'-}\code{-'} (which MIME section boundaries have) but it is declared so it can be overridden in derived classes. This @@ -121,7 +121,7 @@ ignores trailing whitespace. \end{methoddesc} -\begin{methoddesc}{end_marker}{str} +\begin{methoddesc}[MultiFile]{end_marker}{str} Turn a boundary string into an end-marker line. By default, this method prepends \code{'-}\code{-'} and appends \code{'-}\code{-'} (like a MIME-multipart end-of-message marker) but it is declared so it can be @@ -131,11 +131,11 @@ Finally, \class{MultiFile} instances have two public instance variables: -\begin{memberdesc}{level} +\begin{memberdesc}[MultiFile]{level} Nesting depth of the current part. \end{memberdesc} -\begin{memberdesc}{last} +\begin{memberdesc}[MultiFile]{last} True if the last end-of-file was for an end-of-message marker. \end{memberdesc} Modified: python/trunk/Doc/lib/libmutex.tex ============================================================================== --- python/trunk/Doc/lib/libmutex.tex (original) +++ python/trunk/Doc/lib/libmutex.tex Mon Apr 2 00:39:10 2007 @@ -35,23 +35,23 @@ \class{mutex} objects have following methods: -\begin{methoddesc}{test}{} +\begin{methoddesc}[mutex]{test}{} Check whether the mutex is locked. \end{methoddesc} -\begin{methoddesc}{testandset}{} +\begin{methoddesc}[mutex]{testandset}{} ``Atomic'' test-and-set, grab the lock if it is not set, and return \code{True}, otherwise, return \code{False}. \end{methoddesc} -\begin{methoddesc}{lock}{function, argument} +\begin{methoddesc}[mutex]{lock}{function, argument} Execute \code{\var{function}(\var{argument})}, unless the mutex is locked. In the case it is locked, place the function and argument on the queue. See \method{unlock} for explanation of when \code{\var{function}(\var{argument})} is executed in that case. \end{methoddesc} -\begin{methoddesc}{unlock}{} +\begin{methoddesc}[mutex]{unlock}{} Unlock the mutex if queue is empty, otherwise execute the first element in the queue. \end{methoddesc} Modified: python/trunk/Doc/lib/libnetrc.tex ============================================================================== --- python/trunk/Doc/lib/libnetrc.tex (original) +++ python/trunk/Doc/lib/libnetrc.tex Mon Apr 2 00:39:10 2007 @@ -35,7 +35,7 @@ A \class{netrc} instance has the following methods: -\begin{methoddesc}{authenticators}{host} +\begin{methoddesc}[netrc]{authenticators}{host} Return a 3-tuple \code{(\var{login}, \var{account}, \var{password})} of authenticators for \var{host}. If the netrc file did not contain an entry for the given host, return the tuple associated with @@ -43,20 +43,20 @@ available, return \code{None}. \end{methoddesc} -\begin{methoddesc}{__repr__}{} +\begin{methoddesc}[netrc]{__repr__}{} Dump the class data as a string in the format of a netrc file. (This discards comments and may reorder the entries.) \end{methoddesc} Instances of \class{netrc} have public instance variables: -\begin{memberdesc}{hosts} +\begin{memberdesc}[netrc]{hosts} Dictionary mapping host names to \code{(\var{login}, \var{account}, \var{password})} tuples. The `default' entry, if any, is represented as a pseudo-host by that name. \end{memberdesc} -\begin{memberdesc}{macros} +\begin{memberdesc}[netrc]{macros} Dictionary mapping macro names to string lists. \end{memberdesc} Modified: python/trunk/Doc/lib/libnntplib.tex ============================================================================== --- python/trunk/Doc/lib/libnntplib.tex (original) +++ python/trunk/Doc/lib/libnntplib.tex Mon Apr 2 00:39:10 2007 @@ -121,13 +121,13 @@ the above exceptions. -\begin{methoddesc}{getwelcome}{} +\begin{methoddesc}[NNTP]{getwelcome}{} Return the welcome message sent by the server in reply to the initial connection. (This message sometimes contains disclaimers or help information that may be relevant to the user.) \end{methoddesc} -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[NNTP]{set_debuglevel}{level} Set the instance's debugging level. This controls the amount of debugging output printed. The default, \code{0}, produces no debugging output. A value of \code{1} produces a moderate amount of debugging @@ -137,7 +137,7 @@ message text). \end{methoddesc} -\begin{methoddesc}{newgroups}{date, time, \optional{file}} +\begin{methoddesc}[NNTP]{newgroups}{date, time, \optional{file}} Send a \samp{NEWGROUPS} command. The \var{date} argument should be a string of the form \code{'\var{yy}\var{mm}\var{dd}'} indicating the date, and \var{time} should be a string of the form @@ -152,7 +152,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{newnews}{group, date, time, \optional{file}} +\begin{methoddesc}[NNTP]{newnews}{group, date, time, \optional{file}} Send a \samp{NEWNEWS} command. Here, \var{group} is a group name or \code{'*'}, and \var{date} and \var{time} have the same meaning as for \method{newgroups()}. Return a pair \code{(\var{response}, @@ -165,7 +165,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{list}{\optional{file}} +\begin{methoddesc}[NNTP]{list}{\optional{file}} Send a \samp{LIST} command. Return a pair \code{(\var{response}, \var{list})} where \var{list} is a list of tuples. Each tuple has the form \code{(\var{group}, \var{last}, \var{first}, \var{flag})}, where @@ -182,7 +182,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{descriptions}{grouppattern} +\begin{methoddesc}[NNTP]{descriptions}{grouppattern} Send a \samp{LIST NEWSGROUPS} command, where \var{grouppattern} is a wildmat string as specified in RFC2980 (it's essentially the same as DOS or UNIX shell wildcard strings). Return a pair \code{(\var{response}, @@ -192,7 +192,7 @@ \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{description}{group} +\begin{methoddesc}[NNTP]{description}{group} Get a description for a single group \var{group}. If more than one group matches (if 'group' is a real wildmat string), return the first match. If no group matches, return an empty string. @@ -203,7 +203,7 @@ \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{group}{name} +\begin{methoddesc}[NNTP]{group}{name} Send a \samp{GROUP} command, where \var{name} is the group name. Return a tuple \code{(\var{response}, \var{count}, \var{first}, \var{last}, \var{name})} where \var{count} is the (estimated) number @@ -212,7 +212,7 @@ \var{name} is the group name. The numbers are returned as strings. \end{methoddesc} -\begin{methoddesc}{help}{\optional{file}} +\begin{methoddesc}[NNTP]{help}{\optional{file}} Send a \samp{HELP} command. Return a pair \code{(\var{response}, \var{list})} where \var{list} is a list of help strings. If the \var{file} parameter is supplied, then the output of the @@ -223,7 +223,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{stat}{id} +\begin{methoddesc}[NNTP]{stat}{id} Send a \samp{STAT} command, where \var{id} is the message id (enclosed in \character{<} and \character{>}) or an article number (as a string). Return a triple \code{(\var{response}, \var{number}, \var{id})} where @@ -231,15 +231,15 @@ message id (enclosed in \character{<} and \character{>}). \end{methoddesc} -\begin{methoddesc}{next}{} +\begin{methoddesc}[NNTP]{next}{} Send a \samp{NEXT} command. Return as for \method{stat()}. \end{methoddesc} -\begin{methoddesc}{last}{} +\begin{methoddesc}[NNTP]{last}{} Send a \samp{LAST} command. Return as for \method{stat()}. \end{methoddesc} -\begin{methoddesc}{head}{id} +\begin{methoddesc}[NNTP]{head}{id} Send a \samp{HEAD} command, where \var{id} has the same meaning as for \method{stat()}. Return a tuple \code{(\var{response}, \var{number}, \var{id}, \var{list})} @@ -248,7 +248,7 @@ list of lines, without trailing newlines). \end{methoddesc} -\begin{methoddesc}{body}{id,\optional{file}} +\begin{methoddesc}[NNTP]{body}{id,\optional{file}} Send a \samp{BODY} command, where \var{id} has the same meaning as for \method{stat()}. If the \var{file} parameter is supplied, then the body is stored in a file. If \var{file} is a string, then @@ -259,16 +259,16 @@ the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{article}{id} +\begin{methoddesc}[NNTP]{article}{id} Send an \samp{ARTICLE} command, where \var{id} has the same meaning as for \method{stat()}. Return as for \method{head()}. \end{methoddesc} -\begin{methoddesc}{slave}{} +\begin{methoddesc}[NNTP]{slave}{} Send a \samp{SLAVE} command. Return the server's \var{response}. \end{methoddesc} -\begin{methoddesc}{xhdr}{header, string, \optional{file}} +\begin{methoddesc}[NNTP]{xhdr}{header, string, \optional{file}} Send an \samp{XHDR} command. This command is not defined in the RFC but is a common extension. The \var{header} argument is a header keyword, e.g. \code{'subject'}. The \var{string} argument should have @@ -286,7 +286,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{post}{file} +\begin{methoddesc}[NNTP]{post}{file} Post an article using the \samp{POST} command. The \var{file} argument is an open file object which is read until EOF using its \method{readline()} method. It should be a well-formed news article, @@ -294,14 +294,14 @@ automatically escapes lines beginning with \samp{.}. \end{methoddesc} -\begin{methoddesc}{ihave}{id, file} +\begin{methoddesc}[NNTP]{ihave}{id, file} Send an \samp{IHAVE} command. \var{id} is a message id (enclosed in \character{<} and \character{>}). If the response is not an error, treat \var{file} exactly as for the \method{post()} method. \end{methoddesc} -\begin{methoddesc}{date}{} +\begin{methoddesc}[NNTP]{date}{} Return a triple \code{(\var{response}, \var{date}, \var{time})}, containing the current date and time in a form suitable for the \method{newnews()} and \method{newgroups()} methods. @@ -309,7 +309,7 @@ servers. \end{methoddesc} -\begin{methoddesc}{xgtitle}{name, \optional{file}} +\begin{methoddesc}[NNTP]{xgtitle}{name, \optional{file}} Process an \samp{XGTITLE} command, returning a pair \code{(\var{response}, \var{list})}, where \var{list} is a list of tuples containing \code{(\var{name}, \var{title})}. @@ -327,7 +327,7 @@ \method{descriptions()} or \method{description()} instead. \end{methoddesc} -\begin{methoddesc}{xover}{start, end, \optional{file}} +\begin{methoddesc}[NNTP]{xover}{start, end, \optional{file}} Return a pair \code{(\var{resp}, \var{list})}. \var{list} is a list of tuples, one for each article in the range delimited by the \var{start} and \var{end} article numbers. Each tuple is of the form @@ -343,13 +343,13 @@ servers. \end{methoddesc} -\begin{methoddesc}{xpath}{id} +\begin{methoddesc}[NNTP]{xpath}{id} Return a pair \code{(\var{resp}, \var{path})}, where \var{path} is the directory path to the article with message ID \var{id}. This is an optional NNTP extension, and may not be supported by all servers. \end{methoddesc} -\begin{methoddesc}{quit}{} +\begin{methoddesc}[NNTP]{quit}{} Send a \samp{QUIT} command and close the connection. Once this method has been called, no other methods of the NNTP object should be called. \end{methoddesc} Modified: python/trunk/Doc/lib/libpipes.tex ============================================================================== --- python/trunk/Doc/lib/libpipes.tex (original) +++ python/trunk/Doc/lib/libpipes.tex Mon Apr 2 00:39:10 2007 @@ -39,21 +39,21 @@ Template objects following methods: -\begin{methoddesc}{reset}{} +\begin{methoddesc}[Template]{reset}{} Restore a pipeline template to its initial state. \end{methoddesc} -\begin{methoddesc}{clone}{} +\begin{methoddesc}[Template]{clone}{} Return a new, equivalent, pipeline template. \end{methoddesc} -\begin{methoddesc}{debug}{flag} +\begin{methoddesc}[Template]{debug}{flag} If \var{flag} is true, turn debugging on. Otherwise, turn debugging off. When debugging is on, commands to be executed are printed, and the shell is given \code{set -x} command to be more verbose. \end{methoddesc} -\begin{methoddesc}{append}{cmd, kind} +\begin{methoddesc}[Template]{append}{cmd, kind} Append a new action at the end. The \var{cmd} variable must be a valid bourne shell command. The \var{kind} variable consists of two letters. @@ -68,17 +68,17 @@ the command does not write anything, and hence must be last.) \end{methoddesc} -\begin{methoddesc}{prepend}{cmd, kind} +\begin{methoddesc}[Template]{prepend}{cmd, kind} Add a new action at the beginning. See \method{append()} for explanations of the arguments. \end{methoddesc} -\begin{methoddesc}{open}{file, mode} +\begin{methoddesc}[Template]{open}{file, mode} Return a file-like object, open to \var{file}, but read from or written to by the pipeline. Note that only one of \code{'r'}, \code{'w'} may be given. \end{methoddesc} -\begin{methoddesc}{copy}{infile, outfile} +\begin{methoddesc}[Template]{copy}{infile, outfile} Copy \var{infile} to \var{outfile} through the pipe. \end{methoddesc} Modified: python/trunk/Doc/lib/libpopen2.tex ============================================================================== --- python/trunk/Doc/lib/libpopen2.tex (original) +++ python/trunk/Doc/lib/libpopen2.tex Mon Apr 2 00:39:10 2007 @@ -84,12 +84,12 @@ Instances of the \class{Popen3} and \class{Popen4} classes have the following methods: -\begin{methoddesc}{poll}{} +\begin{methoddesc}[Popen3]{poll}{} Returns \code{-1} if child process hasn't completed yet, or its return code otherwise. \end{methoddesc} -\begin{methoddesc}{wait}{} +\begin{methoddesc}[Popen3]{wait}{} Waits for and returns the status code of the child process. The status code encodes both the return code of the process and information about whether it exited using the \cfunction{exit()} @@ -101,24 +101,24 @@ The following attributes are also available: -\begin{memberdesc}{fromchild} +\begin{memberdesc}[Popen3]{fromchild} A file object that provides output from the child process. For \class{Popen4} instances, this will provide both the standard output and standard error streams. \end{memberdesc} -\begin{memberdesc}{tochild} +\begin{memberdesc}[Popen3]{tochild} A file object that provides input to the child process. \end{memberdesc} -\begin{memberdesc}{childerr} +\begin{memberdesc}[Popen3]{childerr} A file object that provides error output from the child process, if \var{capturestderr} was true for the constructor, otherwise \code{None}. This will always be \code{None} for \class{Popen4} instances. \end{memberdesc} -\begin{memberdesc}{pid} +\begin{memberdesc}[Popen3]{pid} The process ID of the child process. \end{memberdesc} Modified: python/trunk/Doc/lib/libpoplib.tex ============================================================================== --- python/trunk/Doc/lib/libpoplib.tex (original) +++ python/trunk/Doc/lib/libpoplib.tex Mon Apr 2 00:39:10 2007 @@ -73,7 +73,7 @@ An \class{POP3} instance has the following methods: -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[POP3]{set_debuglevel}{level} Set the instance's debugging level. This controls the amount of debugging output printed. The default, \code{0}, produces no debugging output. A value of \code{1} produces a moderate amount of @@ -82,64 +82,64 @@ logging each line sent and received on the control connection. \end{methoddesc} -\begin{methoddesc}{getwelcome}{} +\begin{methoddesc}[POP3]{getwelcome}{} Returns the greeting string sent by the POP3 server. \end{methoddesc} -\begin{methoddesc}{user}{username} +\begin{methoddesc}[POP3]{user}{username} Send user command, response should indicate that a password is required. \end{methoddesc} -\begin{methoddesc}{pass_}{password} +\begin{methoddesc}[POP3]{pass_}{password} Send password, response includes message count and mailbox size. Note: the mailbox on the server is locked until \method{quit()} is called. \end{methoddesc} -\begin{methoddesc}{apop}{user, secret} +\begin{methoddesc}[POP3]{apop}{user, secret} Use the more secure APOP authentication to log into the POP3 server. \end{methoddesc} -\begin{methoddesc}{rpop}{user} +\begin{methoddesc}[POP3]{rpop}{user} Use RPOP authentication (similar to UNIX r-commands) to log into POP3 server. \end{methoddesc} -\begin{methoddesc}{stat}{} +\begin{methoddesc}[POP3]{stat}{} Get mailbox status. The result is a tuple of 2 integers: \code{(\var{message count}, \var{mailbox size})}. \end{methoddesc} -\begin{methoddesc}{list}{\optional{which}} +\begin{methoddesc}[POP3]{list}{\optional{which}} Request message list, result is in the form \code{(\var{response}, ['mesg_num octets', ...], \var{octets})}. If \var{which} is set, it is the message to list. \end{methoddesc} -\begin{methoddesc}{retr}{which} +\begin{methoddesc}[POP3]{retr}{which} Retrieve whole message number \var{which}, and set its seen flag. Result is in form \code{(\var{response}, ['line', ...], \var{octets})}. \end{methoddesc} -\begin{methoddesc}{dele}{which} +\begin{methoddesc}[POP3]{dele}{which} Flag message number \var{which} for deletion. On most servers deletions are not actually performed until QUIT (the major exception is Eudora QPOP, which deliberately violates the RFCs by doing pending deletes on any disconnect). \end{methoddesc} -\begin{methoddesc}{rset}{} +\begin{methoddesc}[POP3]{rset}{} Remove any deletion marks for the mailbox. \end{methoddesc} -\begin{methoddesc}{noop}{} +\begin{methoddesc}[POP3]{noop}{} Do nothing. Might be used as a keep-alive. \end{methoddesc} -\begin{methoddesc}{quit}{} +\begin{methoddesc}[POP3]{quit}{} Signoff: commit changes, unlock mailbox, drop connection. \end{methoddesc} -\begin{methoddesc}{top}{which, howmuch} +\begin{methoddesc}[POP3]{top}{which, howmuch} Retrieves the message header plus \var{howmuch} lines of the message after the header of message number \var{which}. Result is in form \code{(\var{response}, ['line', ...], \var{octets})}. @@ -151,7 +151,7 @@ trusting it. \end{methoddesc} -\begin{methoddesc}{uidl}{\optional{which}} +\begin{methoddesc}[POP3]{uidl}{\optional{which}} Return message digest (unique id) list. If \var{which} is specified, result contains the unique id for that message in the form \code{'\var{response}\ \var{mesgnum}\ \var{uid}}, Modified: python/trunk/Doc/lib/libpprint.tex ============================================================================== --- python/trunk/Doc/lib/libpprint.tex (original) +++ python/trunk/Doc/lib/libpprint.tex Mon Apr 2 00:39:10 2007 @@ -158,12 +158,12 @@ \class{PrettyPrinter} instances have the following methods: -\begin{methoddesc}{pformat}{object} +\begin{methoddesc}[PrettyPrinter]{pformat}{object} Return the formatted representation of \var{object}. This takes into account the options passed to the \class{PrettyPrinter} constructor. \end{methoddesc} -\begin{methoddesc}{pprint}{object} +\begin{methoddesc}[PrettyPrinter]{pprint}{object} Print the formatted representation of \var{object} on the configured stream, followed by a newline. \end{methoddesc} @@ -173,7 +173,7 @@ instance is slightly more efficient since new \class{PrettyPrinter} objects don't need to be created. -\begin{methoddesc}{isreadable}{object} +\begin{methoddesc}[PrettyPrinter]{isreadable}{object} Determine if the formatted representation of the object is ``readable,'' or can be used to reconstruct the value using \function{eval()}\bifuncindex{eval}. Note that this returns false for @@ -182,7 +182,7 @@ this returns false. \end{methoddesc} -\begin{methoddesc}{isrecursive}{object} +\begin{methoddesc}[PrettyPrinter]{isrecursive}{object} Determine if the object requires a recursive representation. \end{methoddesc} @@ -190,7 +190,7 @@ way objects are converted to strings. The default implementation uses the internals of the \function{saferepr()} implementation. -\begin{methoddesc}{format}{object, context, maxlevels, level} +\begin{methoddesc}[PrettyPrinter]{format}{object, context, maxlevels, level} Returns three values: the formatted version of \var{object} as a string, a flag indicating whether the result is readable, and a flag indicating whether recursion was detected. The first argument is the Modified: python/trunk/Doc/lib/libqueue.tex ============================================================================== --- python/trunk/Doc/lib/libqueue.tex (original) +++ python/trunk/Doc/lib/libqueue.tex Mon Apr 2 00:39:10 2007 @@ -45,22 +45,22 @@ is not described here. See the source code for details. The public methods are: -\begin{methoddesc}{qsize}{} +\begin{methoddesc}[Queue]{qsize}{} Return the approximate size of the queue. Because of multithreading semantics, this number is not reliable. \end{methoddesc} -\begin{methoddesc}{empty}{} +\begin{methoddesc}[Queue]{empty}{} Return \code{True} if the queue is empty, \code{False} otherwise. Because of multithreading semantics, this is not reliable. \end{methoddesc} -\begin{methoddesc}{full}{} +\begin{methoddesc}[Queue]{full}{} Return \code{True} if the queue is full, \code{False} otherwise. Because of multithreading semantics, this is not reliable. \end{methoddesc} -\begin{methoddesc}{put}{item\optional{, block\optional{, timeout}}} +\begin{methoddesc}[Queue]{put}{item\optional{, block\optional{, timeout}}} Put \var{item} into the queue. If optional args \var{block} is true and \var{timeout} is None (the default), block if necessary until a free slot is available. If \var{timeout} is a positive number, it @@ -74,11 +74,11 @@ \end{methoddesc} -\begin{methoddesc}{put_nowait}{item} +\begin{methoddesc}[Queue]{put_nowait}{item} Equivalent to \code{put(\var{item}, False)}. \end{methoddesc} -\begin{methoddesc}{get}{\optional{block\optional{, timeout}}} +\begin{methoddesc}[Queue]{get}{\optional{block\optional{, timeout}}} Remove and return an item from the queue. If optional args \var{block} is true and \var{timeout} is None (the default), block if necessary until an item is available. If \var{timeout} is @@ -92,14 +92,14 @@ \end{methoddesc} -\begin{methoddesc}{get_nowait}{} +\begin{methoddesc}[Queue]{get_nowait}{} Equivalent to \code{get(False)}. \end{methoddesc} Two methods are offered to support tracking whether enqueued tasks have been fully processed by daemon consumer threads. -\begin{methoddesc}{task_done}{} +\begin{methoddesc}[Queue]{task_done}{} Indicate that a formerly enqueued task is complete. Used by queue consumer threads. For each \method{get()} used to fetch a task, a subsequent call to \method{task_done()} tells the queue that the processing on the task is complete. @@ -113,7 +113,7 @@ \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}{join}{} +\begin{methoddesc}[Queue]{join}{} Blocks until all items in the queue have been gotten and processed. The count of unfinished tasks goes up whenever an item is added to the Modified: python/trunk/Doc/lib/librepr.tex ============================================================================== --- python/trunk/Doc/lib/librepr.tex (original) +++ python/trunk/Doc/lib/librepr.tex Mon Apr 2 00:39:10 2007 @@ -44,18 +44,18 @@ and methods which format specific object types. -\begin{memberdesc}{maxlevel} +\begin{memberdesc}[Repr]{maxlevel} Depth limit on the creation of recursive representations. The default is \code{6}. \end{memberdesc} -\begin{memberdesc}{maxdict} -\memberline{maxlist} -\memberline{maxtuple} -\memberline{maxset} -\memberline{maxfrozenset} -\memberline{maxdeque} -\memberline{maxarray} +\begin{memberdesc}[Repr]{maxdict} +\memberline[Repr]{maxlist} +\memberline[Repr]{maxtuple} +\memberline[Repr]{maxset} +\memberline[Repr]{maxfrozenset} +\memberline[Repr]{maxdeque} +\memberline[Repr]{maxarray} Limits on the number of entries represented for the named object type. The default is \code{4} for \member{maxdict}, \code{5} for \member{maxarray}, and \code{6} for the others. @@ -63,13 +63,13 @@ and \member{set}]{2.4}. \end{memberdesc} -\begin{memberdesc}{maxlong} +\begin{memberdesc}[Repr]{maxlong} Maximum number of characters in the representation for a long integer. Digits are dropped from the middle. The default is \code{40}. \end{memberdesc} -\begin{memberdesc}{maxstring} +\begin{memberdesc}[Repr]{maxstring} Limit on the number of characters in the representation of the string. Note that the ``normal'' representation of the string is used as the character source: if escape sequences are needed in the @@ -77,19 +77,19 @@ shortened. The default is \code{30}. \end{memberdesc} -\begin{memberdesc}{maxother} +\begin{memberdesc}[Repr]{maxother} This limit is used to control the size of object types for which no specific formatting method is available on the \class{Repr} object. It is applied in a similar manner as \member{maxstring}. The default is \code{20}. \end{memberdesc} -\begin{methoddesc}{repr}{obj} +\begin{methoddesc}[Repr]{repr}{obj} The equivalent to the built-in \function{repr()} that uses the formatting imposed by the instance. \end{methoddesc} -\begin{methoddesc}{repr1}{obj, level} +\begin{methoddesc}[Repr]{repr1}{obj, level} Recursive implementation used by \method{repr()}. This uses the type of \var{obj} to determine which formatting method to call, passing it \var{obj} and \var{level}. The type-specific methods @@ -98,7 +98,7 @@ call. \end{methoddesc} -\begin{methoddescni}{repr_\var{type}}{obj, level} +\begin{methoddescni}[Repr]{repr_\var{type}}{obj, level} Formatting methods for specific types are implemented as methods with a name based on the type name. In the method name, \var{type} is replaced by Modified: python/trunk/Doc/lib/librexec.tex ============================================================================== --- python/trunk/Doc/lib/librexec.tex (original) +++ python/trunk/Doc/lib/librexec.tex Mon Apr 2 00:39:10 2007 @@ -89,20 +89,20 @@ \class{RExec} instances support the following methods: -\begin{methoddesc}{r_eval}{code} +\begin{methoddesc}[RExec]{r_eval}{code} \var{code} must either be a string containing a Python expression, or a compiled code object, which will be evaluated in the restricted environment's \module{__main__} module. The value of the expression or code object will be returned. \end{methoddesc} -\begin{methoddesc}{r_exec}{code} +\begin{methoddesc}[RExec]{r_exec}{code} \var{code} must either be a string containing one or more lines of Python code, or a compiled code object, which will be executed in the restricted environment's \module{__main__} module. \end{methoddesc} -\begin{methoddesc}{r_execfile}{filename} +\begin{methoddesc}[RExec]{r_execfile}{filename} Execute the Python code contained in the file \var{filename} in the restricted environment's \module{__main__} module. \end{methoddesc} @@ -112,17 +112,17 @@ restricted versions of the standard I/O streams \code{sys.stdin}, \code{sys.stderr}, and \code{sys.stdout}. -\begin{methoddesc}{s_eval}{code} +\begin{methoddesc}[RExec]{s_eval}{code} \var{code} must be a string containing a Python expression, which will be evaluated in the restricted environment. \end{methoddesc} -\begin{methoddesc}{s_exec}{code} +\begin{methoddesc}[RExec]{s_exec}{code} \var{code} must be a string containing one or more lines of Python code, which will be executed in the restricted environment. \end{methoddesc} -\begin{methoddesc}{s_execfile}{code} +\begin{methoddesc}[RExec]{s_execfile}{code} Execute the Python code contained in the file \var{filename} in the restricted environment. \end{methoddesc} @@ -132,13 +132,13 @@ Overriding these methods in a subclass is used to change the policies enforced by a restricted environment. -\begin{methoddesc}{r_import}{modulename\optional{, globals\optional{, - locals\optional{, fromlist}}}} +\begin{methoddesc}[RExec]{r_import}{modulename\optional{, globals\optional{, + locals\optional{, fromlist}}}} Import the module \var{modulename}, raising an \exception{ImportError} exception if the module is considered unsafe. \end{methoddesc} -\begin{methoddesc}{r_open}{filename\optional{, mode\optional{, bufsize}}} +\begin{methoddesc}[RExec]{r_open}{filename\optional{, mode\optional{, bufsize}}} Method called when \function{open()} is called in the restricted environment. The arguments are identical to those of \function{open()}, and a file object (or a class instance compatible with file objects) @@ -148,28 +148,28 @@ \method{r_open()}. \end{methoddesc} -\begin{methoddesc}{r_reload}{module} +\begin{methoddesc}[RExec]{r_reload}{module} Reload the module object \var{module}, re-parsing and re-initializing it. \end{methoddesc} -\begin{methoddesc}{r_unload}{module} +\begin{methoddesc}[RExec]{r_unload}{module} Unload the module object \var{module} (remove it from the restricted environment's \code{sys.modules} dictionary). \end{methoddesc} And their equivalents with access to restricted standard I/O streams: -\begin{methoddesc}{s_import}{modulename\optional{, globals\optional{, - locals\optional{, fromlist}}}} +\begin{methoddesc}[RExec]{s_import}{modulename\optional{, globals\optional{, + locals\optional{, fromlist}}}} Import the module \var{modulename}, raising an \exception{ImportError} exception if the module is considered unsafe. \end{methoddesc} -\begin{methoddesc}{s_reload}{module} +\begin{methoddesc}[RExec]{s_reload}{module} Reload the module object \var{module}, re-parsing and re-initializing it. \end{methoddesc} -\begin{methoddesc}{s_unload}{module} +\begin{methoddesc}[RExec]{s_unload}{module} Unload the module object \var{module}. % XXX what are the semantics of this? \end{methoddesc} @@ -184,7 +184,7 @@ Instances of the new class will then use those new values. All these attributes are tuples of strings. -\begin{memberdesc}{nok_builtin_names} +\begin{memberdesc}[RExec]{nok_builtin_names} Contains the names of built-in functions which will \emph{not} be available to programs running in the restricted environment. The value for \class{RExec} is \code{('open', 'reload', '__import__')}. @@ -196,7 +196,7 @@ this module.) \end{memberdesc} -\begin{memberdesc}{ok_builtin_modules} +\begin{memberdesc}[RExec]{ok_builtin_modules} Contains the names of built-in modules which can be safely imported. The value for \class{RExec} is \code{('audioop', 'array', 'binascii', 'cmath', 'errno', 'imageop', 'marshal', 'math', 'md5', 'operator', @@ -205,14 +205,14 @@ applies --- use the value from the base class as a starting point. \end{memberdesc} -\begin{memberdesc}{ok_path} +\begin{memberdesc}[RExec]{ok_path} Contains the directories which will be searched when an \keyword{import} is performed in the restricted environment. The value for \class{RExec} is the same as \code{sys.path} (at the time the module is loaded) for unrestricted code. \end{memberdesc} -\begin{memberdesc}{ok_posix_names} +\begin{memberdesc}[RExec]{ok_posix_names} % Should this be called ok_os_names? Contains the names of the functions in the \refmodule{os} module which will be available to programs running in the restricted environment. The @@ -221,14 +221,14 @@ 'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid')}. \end{memberdesc} -\begin{memberdesc}{ok_sys_names} +\begin{memberdesc}[RExec]{ok_sys_names} Contains the names of the functions and variables in the \refmodule{sys} module which will be available to programs running in the restricted environment. The value for \class{RExec} is \code{('ps1', 'ps2', 'copyright', 'version', 'platform', 'exit', 'maxint')}. \end{memberdesc} -\begin{memberdesc}{ok_file_types} +\begin{memberdesc}[RExec]{ok_file_types} Contains the file types from which modules are allowed to be loaded. Each file type is an integer constant defined in the \refmodule{imp} module. The meaningful values are \constant{PY_SOURCE}, \constant{PY_COMPILED}, and Modified: python/trunk/Doc/lib/librfc822.tex ============================================================================== --- python/trunk/Doc/lib/librfc822.tex (original) +++ python/trunk/Doc/lib/librfc822.tex Mon Apr 2 00:39:10 2007 @@ -142,12 +142,12 @@ A \class{Message} instance has the following methods: -\begin{methoddesc}{rewindbody}{} +\begin{methoddesc}[Message]{rewindbody}{} Seek to the start of the message body. This only works if the file object is seekable. \end{methoddesc} -\begin{methoddesc}{isheader}{line} +\begin{methoddesc}[Message]{isheader}{line} Returns a line's canonicalized fieldname (the dictionary key that will be used to index it) if the line is a legal \rfc{2822} header; otherwise returns \code{None} (implying that parsing should stop here and the @@ -155,33 +155,33 @@ override this method in a subclass. \end{methoddesc} -\begin{methoddesc}{islast}{line} +\begin{methoddesc}[Message]{islast}{line} Return true if the given line is a delimiter on which Message should stop. The delimiter line is consumed, and the file object's read location positioned immediately after it. By default this method just checks that the line is blank, but you can override it in a subclass. \end{methoddesc} -\begin{methoddesc}{iscomment}{line} +\begin{methoddesc}[Message]{iscomment}{line} Return \code{True} if the given line should be ignored entirely, just skipped. By default this is a stub that always returns \code{False}, but you can override it in a subclass. \end{methoddesc} -\begin{methoddesc}{getallmatchingheaders}{name} +\begin{methoddesc}[Message]{getallmatchingheaders}{name} Return a list of lines consisting of all headers matching \var{name}, if any. Each physical line, whether it is a continuation line or not, is a separate list item. Return the empty list if no header matches \var{name}. \end{methoddesc} -\begin{methoddesc}{getfirstmatchingheader}{name} +\begin{methoddesc}[Message]{getfirstmatchingheader}{name} Return a list of lines comprising the first header matching \var{name}, and its continuation line(s), if any. Return \code{None} if there is no header matching \var{name}. \end{methoddesc} -\begin{methoddesc}{getrawheader}{name} +\begin{methoddesc}[Message]{getrawheader}{name} Return a single string consisting of the text after the colon in the first header matching \var{name}. This includes leading whitespace, the trailing linefeed, and internal linefeeds and whitespace if there @@ -189,19 +189,19 @@ no header matching \var{name}. \end{methoddesc} -\begin{methoddesc}{getheader}{name\optional{, default}} +\begin{methoddesc}[Message]{getheader}{name\optional{, default}} Like \code{getrawheader(\var{name})}, but strip leading and trailing whitespace. Internal whitespace is not stripped. The optional \var{default} argument can be used to specify a different default to be returned when there is no header matching \var{name}. \end{methoddesc} -\begin{methoddesc}{get}{name\optional{, default}} +\begin{methoddesc}[Message]{get}{name\optional{, default}} An alias for \method{getheader()}, to make the interface more compatible with regular dictionaries. \end{methoddesc} -\begin{methoddesc}{getaddr}{name} +\begin{methoddesc}[Message]{getaddr}{name} Return a pair \code{(\var{full name}, \var{email address})} parsed from the string returned by \code{getheader(\var{name})}. If no header matching \var{name} exists, return \code{(None, None)}; @@ -217,7 +217,7 @@ exact same result. \end{methoddesc} -\begin{methoddesc}{getaddrlist}{name} +\begin{methoddesc}[Message]{getaddrlist}{name} This is similar to \code{getaddr(\var{list})}, but parses a header containing a list of email addresses (e.g.\ a \mailheader{To} header) and returns a list of \code{(\var{full name}, \var{email address})} pairs @@ -229,7 +229,7 @@ Any continuation lines the named headers contain are also parsed. \end{methoddesc} -\begin{methoddesc}{getdate}{name} +\begin{methoddesc}[Message]{getdate}{name} Retrieve a header using \method{getheader()} and parse it into a 9-tuple compatible with \function{time.mktime()}; note that fields 6, 7, and 8 are not usable. If there is no header matching @@ -241,7 +241,7 @@ function may occasionally yield an incorrect result. \end{methoddesc} -\begin{methoddesc}{getdate_tz}{name} +\begin{methoddesc}[Message]{getdate_tz}{name} Retrieve a header using \method{getheader()} and parse it into a 10-tuple; the first 9 elements will make a tuple compatible with \function{time.mktime()}, and the 10th is a number giving the offset @@ -270,19 +270,19 @@ Finally, \class{Message} instances have some public instance variables: -\begin{memberdesc}{headers} +\begin{memberdesc}[Message]{headers} A list containing the entire set of header lines, in the order in which they were read (except that setitem calls may disturb this order). Each line contains a trailing newline. The blank line terminating the headers is not contained in the list. \end{memberdesc} -\begin{memberdesc}{fp} +\begin{memberdesc}[Message]{fp} The file or file-like object passed at instantiation time. This can be used to read the message content. \end{memberdesc} -\begin{memberdesc}{unixfrom} +\begin{memberdesc}[Message]{unixfrom} The \UNIX{} \samp{From~} line, if the message had one, or an empty string. This is needed to regenerate the message in some contexts, such as an \code{mbox}-style mailbox file. @@ -293,34 +293,34 @@ An \class{AddressList} instance has the following methods: -\begin{methoddesc}{__len__}{} +\begin{methoddesc}[AddressList]{__len__}{} Return the number of addresses in the address list. \end{methoddesc} -\begin{methoddesc}{__str__}{} +\begin{methoddesc}[AddressList]{__str__}{} Return a canonicalized string representation of the address list. Addresses are rendered in "name" form, comma-separated. \end{methoddesc} -\begin{methoddesc}{__add__}{alist} +\begin{methoddesc}[AddressList]{__add__}{alist} Return a new \class{AddressList} instance that contains all addresses in both \class{AddressList} operands, with duplicates removed (set union). \end{methoddesc} -\begin{methoddesc}{__iadd__}{alist} +\begin{methoddesc}[AddressList]{__iadd__}{alist} In-place version of \method{__add__()}; turns this \class{AddressList} instance into the union of itself and the right-hand instance, \var{alist}. \end{methoddesc} -\begin{methoddesc}{__sub__}{alist} +\begin{methoddesc}[AddressList]{__sub__}{alist} Return a new \class{AddressList} instance that contains every address in the left-hand \class{AddressList} operand that is not present in the right-hand address operand (set difference). \end{methoddesc} -\begin{methoddesc}{__isub__}{alist} +\begin{methoddesc}[AddressList]{__isub__}{alist} In-place version of \method{__sub__()}, removing addresses in this list which are also in \var{alist}. \end{methoddesc} @@ -328,7 +328,7 @@ Finally, \class{AddressList} instances have one public instance variable: -\begin{memberdesc}{addresslist} +\begin{memberdesc}[AddressList]{addresslist} A list of tuple string pairs, one per address. In each member, the first is the canonicalized name part, the second is the actual route-address (\character{@}-separated username-host.domain Modified: python/trunk/Doc/lib/libsched.tex ============================================================================== --- python/trunk/Doc/lib/libsched.tex (original) +++ python/trunk/Doc/lib/libsched.tex Mon Apr 2 00:39:10 2007 @@ -48,7 +48,7 @@ \class{scheduler} instances have the following methods: -\begin{methoddesc}{enterabs}{time, priority, action, argument} +\begin{methoddesc}[scheduler]{enterabs}{time, priority, action, argument} Schedule a new event. The \var{time} argument should be a numeric type compatible with the return value of the \var{timefunc} function passed to the constructor. Events scheduled for @@ -63,23 +63,23 @@ the event (see \method{cancel()}). \end{methoddesc} -\begin{methoddesc}{enter}{delay, priority, action, argument} +\begin{methoddesc}[scheduler]{enter}{delay, priority, action, argument} Schedule an event for \var{delay} more time units. Other then the relative time, the other arguments, the effect and the return value are the same as those for \method{enterabs()}. \end{methoddesc} -\begin{methoddesc}{cancel}{event} +\begin{methoddesc}[scheduler]{cancel}{event} Remove the event from the queue. If \var{event} is not an event currently in the queue, this method will raise a \exception{RuntimeError}. \end{methoddesc} -\begin{methoddesc}{empty}{} +\begin{methoddesc}[scheduler]{empty}{} Return true if the event queue is empty. \end{methoddesc} -\begin{methoddesc}{run}{} +\begin{methoddesc}[scheduler]{run}{} Run all scheduled events. This function will wait (using the \function{delayfunc} function passed to the constructor) for the next event, then execute it and so on until there are no more Modified: python/trunk/Doc/lib/libshlex.tex ============================================================================== --- python/trunk/Doc/lib/libshlex.tex (original) +++ python/trunk/Doc/lib/libshlex.tex Mon Apr 2 00:39:10 2007 @@ -58,7 +58,7 @@ A \class{shlex} instance has the following methods: -\begin{methoddesc}{get_token}{} +\begin{methoddesc}[shlex]{get_token}{} Return a token. If tokens have been stacked using \method{push_token()}, pop a token off the stack. Otherwise, read one from the input stream. If reading encounters an immediate @@ -66,17 +66,17 @@ in non-\POSIX{} mode, and \code{None} in \POSIX{} mode). \end{methoddesc} -\begin{methoddesc}{push_token}{str} +\begin{methoddesc}[shlex]{push_token}{str} Push the argument onto the token stack. \end{methoddesc} -\begin{methoddesc}{read_token}{} +\begin{methoddesc}[shlex]{read_token}{} Read a raw token. Ignore the pushback stack, and do not interpret source requests. (This is not ordinarily a useful entry point, and is documented here only for the sake of completeness.) \end{methoddesc} -\begin{methoddesc}{sourcehook}{filename} +\begin{methoddesc}[shlex]{sourcehook}{filename} When \class{shlex} detects a source request (see \member{source} below) this method is given the following token as argument, and expected to return a tuple consisting of a filename and @@ -106,7 +106,7 @@ \method{push_source()} and \method{pop_source()} methods. \end{methoddesc} -\begin{methoddesc}{push_source}{stream\optional{, filename}} +\begin{methoddesc}[shlex]{push_source}{stream\optional{, filename}} Push an input source stream onto the input stack. If the filename argument is specified it will later be available for use in error messages. This is the same method used internally by the @@ -114,14 +114,14 @@ \versionadded{2.1} \end{methoddesc} -\begin{methoddesc}{pop_source}{} +\begin{methoddesc}[shlex]{pop_source}{} Pop the last-pushed input source from the input stack. This is the same method used internally when the lexer reaches \EOF{} on a stacked input stream. \versionadded{2.1} \end{methoddesc} -\begin{methoddesc}{error_leader}{\optional{file\optional{, line}}} +\begin{methoddesc}[shlex]{error_leader}{\optional{file\optional{, line}}} This method generates an error message leader in the format of a \UNIX{} C compiler error label; the format is \code{'"\%s", line \%d: '}, where the \samp{\%s} is replaced with the name of the current source @@ -137,63 +137,63 @@ variables which either control lexical analysis or can be used for debugging: -\begin{memberdesc}{commenters} +\begin{memberdesc}[shlex]{commenters} The string of characters that are recognized as comment beginners. All characters from the comment beginner to end of line are ignored. Includes just \character{\#} by default. \end{memberdesc} -\begin{memberdesc}{wordchars} +\begin{memberdesc}[shlex]{wordchars} The string of characters that will accumulate into multi-character tokens. By default, includes all \ASCII{} alphanumerics and underscore. \end{memberdesc} -\begin{memberdesc}{whitespace} +\begin{memberdesc}[shlex]{whitespace} Characters that will be considered whitespace and skipped. Whitespace bounds tokens. By default, includes space, tab, linefeed and carriage-return. \end{memberdesc} -\begin{memberdesc}{escape} +\begin{memberdesc}[shlex]{escape} Characters that will be considered as escape. This will be only used in \POSIX{} mode, and includes just \character{\textbackslash} by default. \versionadded{2.3} \end{memberdesc} -\begin{memberdesc}{quotes} +\begin{memberdesc}[shlex]{quotes} Characters that will be considered string quotes. The token accumulates until the same quote is encountered again (thus, different quote types protect each other as in the shell.) By default, includes \ASCII{} single and double quotes. \end{memberdesc} -\begin{memberdesc}{escapedquotes} +\begin{memberdesc}[shlex]{escapedquotes} Characters in \member{quotes} that will interpret escape characters defined in \member{escape}. This is only used in \POSIX{} mode, and includes just \character{"} by default. \versionadded{2.3} \end{memberdesc} -\begin{memberdesc}{whitespace_split} +\begin{memberdesc}[shlex]{whitespace_split} If \code{True}, tokens will only be split in whitespaces. This is useful, for example, for parsing command lines with \class{shlex}, getting tokens in a similar way to shell arguments. \versionadded{2.3} \end{memberdesc} -\begin{memberdesc}{infile} +\begin{memberdesc}[shlex]{infile} The name of the current input file, as initially set at class instantiation time or stacked by later source requests. It may be useful to examine this when constructing error messages. \end{memberdesc} -\begin{memberdesc}{instream} +\begin{memberdesc}[shlex]{instream} The input stream from which this \class{shlex} instance is reading characters. \end{memberdesc} -\begin{memberdesc}{source} +\begin{memberdesc}[shlex]{source} This member is \code{None} by default. If you assign a string to it, that string will be recognized as a lexical-level inclusion request similar to the \samp{source} keyword in various shells. That is, the @@ -204,23 +204,23 @@ number of levels deep. \end{memberdesc} -\begin{memberdesc}{debug} +\begin{memberdesc}[shlex]{debug} If this member is numeric and \code{1} or more, a \class{shlex} instance will print verbose progress output on its behavior. If you need to use this, you can read the module source code to learn the details. \end{memberdesc} -\begin{memberdesc}{lineno} +\begin{memberdesc}[shlex]{lineno} Source line number (count of newlines seen so far plus one). \end{memberdesc} -\begin{memberdesc}{token} +\begin{memberdesc}[shlex]{token} The token buffer. It may be useful to examine this when catching exceptions. \end{memberdesc} -\begin{memberdesc}{eof} +\begin{memberdesc}[shlex]{eof} Token used to determine end of file. This will be set to the empty string (\code{''}), in non-\POSIX{} mode, and to \code{None} in \POSIX{} mode. Modified: python/trunk/Doc/lib/libsimplexmlrpc.tex ============================================================================== --- python/trunk/Doc/lib/libsimplexmlrpc.tex (original) +++ python/trunk/Doc/lib/libsimplexmlrpc.tex Mon Apr 2 00:39:10 2007 @@ -108,13 +108,13 @@ \end{methoddesc} -\begin{methoddesc}{register_introspection_functions}{} +\begin{methoddesc}[SimpleXMLRPCServer]{register_introspection_functions}{} Registers the XML-RPC introspection functions \code{system.listMethods}, \code{system.methodHelp} and \code{system.methodSignature}. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{register_multicall_functions}{} +\begin{methoddesc}[SimpleXMLRPCServer]{register_multicall_functions}{} Registers the XML-RPC multicall function system.multicall. \end{methoddesc} @@ -178,7 +178,7 @@ The \class{CGIXMLRPCRequestHandler} class can be used to handle XML-RPC requests sent to Python CGI scripts. -\begin{methoddesc}{register_function}{function\optional{, name}} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{register_function}{function\optional{, name}} Register a function that can respond to XML-RPC requests. If \var{name} is given, it will be the method name associated with function, otherwise \var{function.__name__} will be used. \var{name} @@ -187,7 +187,7 @@ character. \end{methoddesc} -\begin{methoddesc}{register_instance}{instance} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{register_instance}{instance} Register an object which is used to expose method names which have not been registered using \method{register_function()}. If instance contains a \method{_dispatch()} method, it is called with the @@ -203,17 +203,17 @@ back to the client. \end{methoddesc} -\begin{methoddesc}{register_introspection_functions}{} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{register_introspection_functions}{} Register the XML-RPC introspection functions \code{system.listMethods}, \code{system.methodHelp} and \code{system.methodSignature}. \end{methoddesc} -\begin{methoddesc}{register_multicall_functions}{} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{register_multicall_functions}{} Register the XML-RPC multicall function \code{system.multicall}. \end{methoddesc} -\begin{methoddesc}{handle_request}{\optional{request_text = None}} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{handle_request}{\optional{request_text = None}} Handle a XML-RPC request. If \var{request_text} is given, it should be the POST data provided by the HTTP server, otherwise the contents of stdin will be used. Modified: python/trunk/Doc/lib/libsmtplib.tex ============================================================================== --- python/trunk/Doc/lib/libsmtplib.tex (original) +++ python/trunk/Doc/lib/libsmtplib.tex Mon Apr 2 00:39:10 2007 @@ -126,13 +126,13 @@ An \class{SMTP} instance has the following methods: -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[SMTP]{set_debuglevel}{level} Set the debug output level. A true value for \var{level} results in debug messages for connection and for all messages sent to and received from the server. \end{methoddesc} -\begin{methoddesc}{connect}{\optional{host\optional{, port}}} +\begin{methoddesc}[SMTP]{connect}{\optional{host\optional{, port}}} Connect to a host on a given port. The defaults are to connect to the local host at the standard SMTP port (25). If the hostname ends with a colon (\character{:}) followed by a @@ -142,7 +142,7 @@ host is specified during instantiation. \end{methoddesc} -\begin{methoddesc}{docmd}{cmd, \optional{, argstring}} +\begin{methoddesc}[SMTP]{docmd}{cmd, \optional{, argstring}} Send a command \var{cmd} to the server. The optional argument \var{argstring} is simply concatenated to the command, separated by a space. @@ -159,7 +159,7 @@ \exception{SMTPServerDisconnected} will be raised. \end{methoddesc} -\begin{methoddesc}{helo}{\optional{hostname}} +\begin{methoddesc}[SMTP]{helo}{\optional{hostname}} Identify yourself to the SMTP server using \samp{HELO}. The hostname argument defaults to the fully qualified domain name of the local host. @@ -169,7 +169,7 @@ when necessary. \end{methoddesc} -\begin{methoddesc}{ehlo}{\optional{hostname}} +\begin{methoddesc}[SMTP]{ehlo}{\optional{hostname}} Identify yourself to an ESMTP server using \samp{EHLO}. The hostname argument defaults to the fully qualified domain name of the local host. Examine the response for ESMTP option and store them for use by @@ -180,13 +180,13 @@ will be implicitly called by \method{sendmail()} when necessary. \end{methoddesc} -\begin{methoddesc}{has_extn}{name} +\begin{methoddesc}[SMTP]{has_extn}{name} Return \constant{True} if \var{name} is in the set of SMTP service extensions returned by the server, \constant{False} otherwise. Case is ignored. \end{methoddesc} -\begin{methoddesc}{verify}{address} +\begin{methoddesc}[SMTP]{verify}{address} Check the validity of an address on this server using SMTP \samp{VRFY}. Returns a tuple consisting of code 250 and a full \rfc{822} address (including human name) if the user address is valid. Otherwise returns @@ -195,7 +195,7 @@ \note{Many sites disable SMTP \samp{VRFY} in order to foil spammers.} \end{methoddesc} -\begin{methoddesc}{login}{user, password} +\begin{methoddesc}[SMTP]{login}{user, password} Log in on an SMTP server that requires authentication. The arguments are the username and the password to authenticate with. If there has been no previous \samp{EHLO} or \samp{HELO} command this @@ -213,7 +213,7 @@ \end{description} \end{methoddesc} -\begin{methoddesc}{starttls}{\optional{keyfile\optional{, certfile}}} +\begin{methoddesc}[SMTP]{starttls}{\optional{keyfile\optional{, certfile}}} Put the SMTP connection in TLS (Transport Layer Security) mode. All SMTP commands that follow will be encrypted. You should then call \method{ehlo()} again. @@ -222,8 +222,8 @@ the \refmodule{socket} module's \function{ssl()} function. \end{methoddesc} -\begin{methoddesc}{sendmail}{from_addr, to_addrs, msg\optional{, - mail_options, rcpt_options}} +\begin{methoddesc}[SMTP]{sendmail}{from_addr, to_addrs, msg\optional{, + mail_options, rcpt_options}} Send mail. The required arguments are an \rfc{822} from-address string, a list of \rfc{822} to-address strings (a bare string will be treated as a list with 1 address), and a message string. The caller @@ -279,7 +279,7 @@ \end{methoddesc} -\begin{methoddesc}{quit}{} +\begin{methoddesc}[SMTP]{quit}{} Terminate the SMTP session and close the connection. \end{methoddesc} Modified: python/trunk/Doc/lib/libsubprocess.tex ============================================================================== --- python/trunk/Doc/lib/libsubprocess.tex (original) +++ python/trunk/Doc/lib/libsubprocess.tex Mon Apr 2 00:39:10 2007 @@ -176,16 +176,16 @@ Instances of the \class{Popen} class have the following methods: -\begin{methoddesc}{poll}{} +\begin{methoddesc}[Popen]{poll}{} Check if child process has terminated. Returns returncode attribute. \end{methoddesc} -\begin{methoddesc}{wait}{} +\begin{methoddesc}[Popen]{wait}{} Wait for child process to terminate. Returns returncode attribute. \end{methoddesc} -\begin{methoddesc}{communicate}{input=None} +\begin{methoddesc}[Popen]{communicate}{input=None} Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional \var{input} argument should be a string to be sent to the @@ -199,29 +199,29 @@ The following attributes are also available: -\begin{memberdesc}{stdin} +\begin{memberdesc}[Popen]{stdin} If the \var{stdin} argument is \code{PIPE}, this attribute is a file object that provides input to the child process. Otherwise, it is \code{None}. \end{memberdesc} -\begin{memberdesc}{stdout} +\begin{memberdesc}[Popen]{stdout} If the \var{stdout} argument is \code{PIPE}, this attribute is a file object that provides output from the child process. Otherwise, it is \code{None}. \end{memberdesc} -\begin{memberdesc}{stderr} +\begin{memberdesc}[Popen]{stderr} If the \var{stderr} argument is \code{PIPE}, this attribute is file object that provides error output from the child process. Otherwise, it is \code{None}. \end{memberdesc} -\begin{memberdesc}{pid} +\begin{memberdesc}[Popen]{pid} The process ID of the child process. \end{memberdesc} -\begin{memberdesc}{returncode} +\begin{memberdesc}[Popen]{returncode} The child return code. A \code{None} value indicates that the process hasn't terminated yet. A negative value -N indicates that the child was terminated by signal N (\UNIX{} only). Modified: python/trunk/Doc/lib/libtelnetlib.tex ============================================================================== --- python/trunk/Doc/lib/libtelnetlib.tex (original) +++ python/trunk/Doc/lib/libtelnetlib.tex Mon Apr 2 00:39:10 2007 @@ -55,7 +55,7 @@ \class{Telnet} instances have the following methods: -\begin{methoddesc}{read_until}{expected\optional{, timeout}} +\begin{methoddesc}[Telnet]{read_until}{expected\optional{, timeout}} Read until a given string, \var{expected}, is encountered or until \var{timeout} seconds have passed. @@ -64,17 +64,17 @@ is closed and no cooked data is available. \end{methoddesc} -\begin{methoddesc}{read_all}{} +\begin{methoddesc}[Telnet]{read_all}{} Read all data until \EOF; block until connection closed. \end{methoddesc} -\begin{methoddesc}{read_some}{} +\begin{methoddesc}[Telnet]{read_some}{} Read at least one byte of cooked data unless \EOF{} is hit. Return \code{''} if \EOF{} is hit. Block if no data is immediately available. \end{methoddesc} -\begin{methoddesc}{read_very_eager}{} +\begin{methoddesc}[Telnet]{read_very_eager}{} Read everything that can be without blocking in I/O (eager). Raise \exception{EOFError} if connection closed and no cooked data @@ -82,7 +82,7 @@ Do not block unless in the midst of an IAC sequence. \end{methoddesc} -\begin{methoddesc}{read_eager}{} +\begin{methoddesc}[Telnet]{read_eager}{} Read readily available data. Raise \exception{EOFError} if connection closed and no cooked data @@ -90,7 +90,7 @@ Do not block unless in the midst of an IAC sequence. \end{methoddesc} -\begin{methoddesc}{read_lazy}{} +\begin{methoddesc}[Telnet]{read_lazy}{} Process and return data already in the queues (lazy). Raise \exception{EOFError} if connection closed and no data available. @@ -98,7 +98,7 @@ unless in the midst of an IAC sequence. \end{methoddesc} -\begin{methoddesc}{read_very_lazy}{} +\begin{methoddesc}[Telnet]{read_very_lazy}{} Return any data available in the cooked queue (very lazy). Raise \exception{EOFError} if connection closed and no data available. @@ -106,7 +106,7 @@ never blocks. \end{methoddesc} -\begin{methoddesc}{read_sb_data}{} +\begin{methoddesc}[Telnet]{read_sb_data}{} Return the data collected between a SB/SE pair (suboption begin/end). The callback should access these data when it was invoked with a \code{SE} command. This method never blocks. @@ -114,7 +114,7 @@ \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{open}{host\optional{, port\optional{, timeout}}} +\begin{methoddesc}[Telnet]{open}{host\optional{, port\optional{, timeout}}} Connect to a host. The optional second argument is the port number, which defaults to the standard Telnet port (23). @@ -125,44 +125,44 @@ Do not try to reopen an already connected instance. \end{methoddesc} -\begin{methoddesc}{msg}{msg\optional{, *args}} +\begin{methoddesc}[Telnet]{msg}{msg\optional{, *args}} Print a debug message when the debug level is \code{>} 0. If extra arguments are present, they are substituted in the message using the standard string formatting operator. \end{methoddesc} -\begin{methoddesc}{set_debuglevel}{debuglevel} +\begin{methoddesc}[Telnet]{set_debuglevel}{debuglevel} Set the debug level. The higher the value of \var{debuglevel}, the more debug output you get (on \code{sys.stdout}). \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[Telnet]{close}{} Close the connection. \end{methoddesc} -\begin{methoddesc}{get_socket}{} +\begin{methoddesc}[Telnet]{get_socket}{} Return the socket object used internally. \end{methoddesc} -\begin{methoddesc}{fileno}{} +\begin{methoddesc}[Telnet]{fileno}{} Return the file descriptor of the socket object used internally. \end{methoddesc} -\begin{methoddesc}{write}{buffer} +\begin{methoddesc}[Telnet]{write}{buffer} Write a string to the socket, doubling any IAC characters. This can block if the connection is blocked. May raise \exception{socket.error} if the connection is closed. \end{methoddesc} -\begin{methoddesc}{interact}{} +\begin{methoddesc}[Telnet]{interact}{} Interaction function, emulates a very dumb Telnet client. \end{methoddesc} -\begin{methoddesc}{mt_interact}{} +\begin{methoddesc}[Telnet]{mt_interact}{} Multithreaded version of \method{interact()}. \end{methoddesc} -\begin{methoddesc}{expect}{list\optional{, timeout}} +\begin{methoddesc}[Telnet]{expect}{list\optional{, timeout}} Read until one from a list of a regular expressions matches. The first argument is a list of regular expressions, either @@ -184,7 +184,7 @@ results are indeterministic, and may depend on the I/O timing. \end{methoddesc} -\begin{methoddesc}{set_option_negotiation_callback}{callback} +\begin{methoddesc}[Telnet]{set_option_negotiation_callback}{callback} Each time a telnet option is read on the input flow, this \var{callback} (if set) is called with the following parameters : callback(telnet socket, command (DO/DONT/WILL/WONT), option). No other Modified: python/trunk/Doc/lib/libthreading.tex ============================================================================== --- python/trunk/Doc/lib/libthreading.tex (original) +++ python/trunk/Doc/lib/libthreading.tex Mon Apr 2 00:39:10 2007 @@ -20,11 +20,11 @@ \function{enumerate()}. \end{funcdesc} -\begin{funcdesc}{Condition}{} +\begin{funcdescni}{Condition}{} A factory function that returns a new condition variable object. A condition variable allows one or more threads to wait until they are notified by another thread. -\end{funcdesc} +\end{funcdescni} \begin{funcdesc}{currentThread}{} Return the current \class{Thread} object, corresponding to the @@ -41,12 +41,12 @@ terminated threads and threads that have not yet been started. \end{funcdesc} -\begin{funcdesc}{Event}{} +\begin{funcdescni}{Event}{} A factory function that returns a new event object. An event manages a flag that can be set to true with the \method{set()} method and reset to false with the \method{clear()} method. The \method{wait()} method blocks until the flag is true. -\end{funcdesc} +\end{funcdescni} \begin{classdesc*}{local}{} A class that represents thread-local data. Thread-local data are data @@ -81,14 +81,14 @@ for each time it has acquired it. \end{funcdesc} -\begin{funcdesc}{Semaphore}{\optional{value}} +\begin{funcdescni}{Semaphore}{\optional{value}} A factory function that returns a new semaphore object. A semaphore manages a counter representing the number of \method{release()} calls minus the number of \method{acquire()} calls, plus an initial value. The \method{acquire()} method blocks if necessary until it can return without making the counter negative. If not given, \var{value} defaults to 1. -\end{funcdesc} +\end{funcdescni} \begin{funcdesc}{BoundedSemaphore}{\optional{value}} A factory function that returns a new bounded semaphore object. A bounded @@ -99,12 +99,12 @@ \var{value} defaults to 1. \end{funcdesc} -\begin{classdesc*}{Thread}{} +\begin{classdesc*}{Thread} A class that represents a thread of control. This class can be safely subclassed in a limited fashion. \end{classdesc*} -\begin{classdesc*}{Timer}{} +\begin{classdesc*}{Timer} A thread that executes a function after a specified interval has passed. \end{classdesc*} @@ -182,7 +182,7 @@ All methods are executed atomically. -\begin{methoddesc}{acquire}{\optional{blocking\code{ = 1}}} +\begin{methoddesc}[Lock]{acquire}{\optional{blocking\code{ = 1}}} Acquire a lock, blocking or non-blocking. When invoked without arguments, block until the lock is @@ -197,7 +197,7 @@ without arguments, and return true. \end{methoddesc} -\begin{methoddesc}{release}{} +\begin{methoddesc}[Lock]{release}{} Release a lock. When the lock is locked, reset it to unlocked, and return. If @@ -227,7 +227,7 @@ pair) resets the lock to unlocked and allows another thread blocked in \method{acquire()} to proceed. -\begin{methoddesc}{acquire}{\optional{blocking\code{ = 1}}} +\begin{methoddesc}[RLock]{acquire}{\optional{blocking\code{ = 1}}} Acquire a lock, blocking or non-blocking. When invoked without arguments: if this thread already owns @@ -249,7 +249,7 @@ without arguments, and return true. \end{methoddesc} -\begin{methoddesc}{release}{} +\begin{methoddesc}[RLock]{release}{} Release a lock, decrementing the recursion level. If after the decrement it is zero, reset the lock to unlocked (not owned by any thread), and if any other threads are blocked waiting for the lock to Modified: python/trunk/Doc/lib/libturtle.tex ============================================================================== --- python/trunk/Doc/lib/libturtle.tex (original) +++ python/trunk/Doc/lib/libturtle.tex Mon Apr 2 00:39:10 2007 @@ -261,7 +261,7 @@ \function{degrees()}, which takes an optional argument letting you specify the number of units corresponding to a full circle: -\begin{methoddesc}{degrees}{\optional{fullcircle}} +\begin{methoddesc}[Turtle]{degrees}{\optional{fullcircle}} \var{fullcircle} is by default 360. This can cause the pen to have any angular units whatever: give \var{fullcircle} 2*$\pi$ for radians, or 400 for gradians. Modified: python/trunk/Doc/lib/libunittest.tex ============================================================================== --- python/trunk/Doc/lib/libunittest.tex (original) +++ python/trunk/Doc/lib/libunittest.tex Mon Apr 2 00:39:10 2007 @@ -619,14 +619,14 @@ report failures. \begin{methoddesc}[TestCase]{assert_}{expr\optional{, msg}} -\methodline{failUnless}{expr\optional{, msg}} +\methodline[TestCase]{failUnless}{expr\optional{, msg}} Signal a test failure if \var{expr} is false; the explanation for the error will be \var{msg} if given, otherwise it will be \constant{None}. \end{methoddesc} \begin{methoddesc}[TestCase]{assertEqual}{first, second\optional{, msg}} -\methodline{failUnlessEqual}{first, second\optional{, msg}} +\methodline[TestCase]{failUnlessEqual}{first, second\optional{, msg}} Test that \var{first} and \var{second} are equal. If the values do not compare equal, the test will fail with the explanation given by \var{msg}, or \constant{None}. Note that using \method{failUnlessEqual()} @@ -637,7 +637,7 @@ \end{methoddesc} \begin{methoddesc}[TestCase]{assertNotEqual}{first, second\optional{, msg}} -\methodline{failIfEqual}{first, second\optional{, msg}} +\methodline[TestCase]{failIfEqual}{first, second\optional{, msg}} Test that \var{first} and \var{second} are not equal. If the values do compare equal, the test will fail with the explanation given by \var{msg}, or \constant{None}. Note that using \method{failIfEqual()} @@ -649,7 +649,7 @@ \begin{methoddesc}[TestCase]{assertAlmostEqual}{first, second\optional{, places\optional{, msg}}} -\methodline{failUnlessAlmostEqual}{first, second\optional{, +\methodline[TestCase]{failUnlessAlmostEqual}{first, second\optional{, places\optional{, msg}}} Test that \var{first} and \var{second} are approximately equal by computing the difference, rounding to the given number of \var{places}, @@ -661,7 +661,7 @@ \begin{methoddesc}[TestCase]{assertNotAlmostEqual}{first, second\optional{, places\optional{, msg}}} -\methodline{failIfAlmostEqual}{first, second\optional{, +\methodline[TestCase]{failIfAlmostEqual}{first, second\optional{, places\optional{, msg}}} Test that \var{first} and \var{second} are not approximately equal by computing the difference, rounding to the given number of \var{places}, @@ -672,7 +672,7 @@ \end{methoddesc} \begin{methoddesc}[TestCase]{assertRaises}{exception, callable, \moreargs} -\methodline{failUnlessRaises}{exception, callable, \moreargs} +\methodline[TestCase]{failUnlessRaises}{exception, callable, \moreargs} Test that an exception is raised when \var{callable} is called with any positional or keyword arguments that are also passed to \method{assertRaises()}. The test passes if \var{exception} is Modified: python/trunk/Doc/lib/liburllib2.tex ============================================================================== --- python/trunk/Doc/lib/liburllib2.tex (original) +++ python/trunk/Doc/lib/liburllib2.tex Mon Apr 2 00:39:10 2007 @@ -588,7 +588,7 @@ \class{HTTPCookieProcessor} instances have one attribute: -\begin{memberdesc}{cookiejar} +\begin{memberdesc}[HTTPCookieProcessor]{cookiejar} The \class{cookielib.CookieJar} in which cookies are stored. \end{memberdesc} Modified: python/trunk/Doc/lib/libxmlrpclib.tex ============================================================================== --- python/trunk/Doc/lib/libxmlrpclib.tex (original) +++ python/trunk/Doc/lib/libxmlrpclib.tex Mon Apr 2 00:39:10 2007 @@ -134,12 +134,12 @@ Servers that support the XML introspection API support some common methods grouped under the reserved \member{system} member: -\begin{methoddesc}{system.listMethods}{} +\begin{methoddesc}[ServerProxy]{system.listMethods}{} This method returns a list of strings, one for each (non-system) method supported by the XML-RPC server. \end{methoddesc} -\begin{methoddesc}{system.methodSignature}{name} +\begin{methoddesc}[ServerProxy]{system.methodSignature}{name} This method takes one parameter, the name of a method implemented by the XML-RPC server.It returns an array of possible signatures for this method. A signature is an array of types. The first of these types is @@ -159,7 +159,7 @@ value will be something other that list. \end{methoddesc} -\begin{methoddesc}{system.methodHelp}{name} +\begin{methoddesc}[ServerProxy]{system.methodHelp}{name} This method takes one parameter, the name of a method implemented by the XML-RPC server. It returns a documentation string describing the use of that method. If no such string is available, an empty string is @@ -184,7 +184,7 @@ It also has the following method, supported mainly for internal use by the unmarshalling code: -\begin{methoddesc}{encode}{out} +\begin{methoddesc}[Boolean]{encode}{out} Write the XML-RPC encoding of this Boolean item to the out stream object. \end{methoddesc} @@ -197,11 +197,11 @@ instance. It has the following methods, supported mainly for internal use by the marshalling/unmarshalling code: -\begin{methoddesc}{decode}{string} +\begin{methoddesc}[DateTime]{decode}{string} Accept a string as the instance's new time value. \end{methoddesc} -\begin{methoddesc}{encode}{out} +\begin{methoddesc}[DateTime]{encode}{out} Write the XML-RPC encoding of this \class{DateTime} item to the \var{out} stream object. \end{methoddesc} @@ -242,11 +242,11 @@ A \class{Fault} object encapsulates the content of an XML-RPC fault tag. Fault objects have the following members: -\begin{memberdesc}{faultCode} +\begin{memberdesc}[Fault]{faultCode} A string indicating the fault type. \end{memberdesc} -\begin{memberdesc}{faultString} +\begin{memberdesc}[Fault]{faultString} A string containing a diagnostic message associated with the fault. \end{memberdesc} @@ -258,19 +258,19 @@ server named by the URI does not exist). It has the following members: -\begin{memberdesc}{url} +\begin{memberdesc}[ProtocolError]{url} The URI or URL that triggered the error. \end{memberdesc} -\begin{memberdesc}{errcode} +\begin{memberdesc}[ProtocolError]{errcode} The error code. \end{memberdesc} -\begin{memberdesc}{errmsg} +\begin{memberdesc}[ProtocolError]{errmsg} The error message or diagnostic string. \end{memberdesc} -\begin{memberdesc}{headers} +\begin{memberdesc}[ProtocolError]{headers} A string containing the headers of the HTTP/HTTPS request that triggered the error. \end{memberdesc} Modified: python/trunk/Doc/mac/libmacic.tex ============================================================================== --- python/trunk/Doc/mac/libmacic.tex (original) +++ python/trunk/Doc/mac/libmacic.tex Mon Apr 2 00:39:10 2007 @@ -68,14 +68,14 @@ following methods: -\begin{methoddesc}{launchurl}{url\optional{, hint}} +\begin{methoddesc}[IC]{launchurl}{url\optional{, hint}} Parse the given URL, launch the correct application and pass it the URL. The optional \var{hint} can be a scheme name such as \code{'mailto:'}, in which case incomplete URLs are completed with this scheme. If \var{hint} is not provided, incomplete URLs are invalid. \end{methoddesc} -\begin{methoddesc}{parseurl}{data\optional{, start\optional{, end\optional{, hint}}}} +\begin{methoddesc}[IC]{parseurl}{data\optional{, start\optional{, end\optional{, hint}}}} Find an URL somewhere in \var{data} and return start position, end position and the URL. The optional \var{start} and \var{end} can be used to limit the search, so for instance if a user clicks in a long @@ -85,7 +85,7 @@ complete incomplete URLs. \end{methoddesc} -\begin{methoddesc}{mapfile}{file} +\begin{methoddesc}[IC]{mapfile}{file} Return the mapping entry for the given \var{file}, which can be passed as either a filename or an \function{FSSpec()} result, and which need not exist. @@ -106,7 +106,7 @@ file and \var{entryname} is the name of this entry. \end{methoddesc} -\begin{methoddesc}{maptypecreator}{type, creator\optional{, filename}} +\begin{methoddesc}[IC]{maptypecreator}{type, creator\optional{, filename}} Return the mapping entry for files with given 4-character \var{type} and \var{creator} codes. The optional \var{filename} may be specified to further help finding the correct entry (if the creator code is @@ -115,7 +115,7 @@ The mapping entry is returned in the same format as for \var{mapfile}. \end{methoddesc} -\begin{methoddesc}{settypecreator}{file} +\begin{methoddesc}[IC]{settypecreator}{file} Given an existing \var{file}, specified either as a filename or as an \function{FSSpec()} result, set its creator and type correctly based on its extension. The finder is told about the change, so the finder From python-checkins at python.org Mon Apr 2 00:40:13 2007 From: python-checkins at python.org (georg.brandl) Date: Mon, 2 Apr 2007 00:40:13 +0200 (CEST) Subject: [Python-checkins] r54652 - python/trunk/Doc/dist/dist.tex Message-ID: <20070401224013.222401E400A@bag.python.org> Author: georg.brandl Date: Mon Apr 2 00:40:12 2007 New Revision: 54652 Modified: python/trunk/Doc/dist/dist.tex Log: Explicit class names. Modified: python/trunk/Doc/dist/dist.tex ============================================================================== --- python/trunk/Doc/dist/dist.tex (original) +++ python/trunk/Doc/dist/dist.tex Mon Apr 2 00:40:12 2007 @@ -3733,7 +3733,7 @@ Subclasses of \class{Command} must define the following methods. -\begin{methoddesc}{initialize_options()} +\begin{methoddesc}[Command]{initialize_options()} Set default values for all the options that this command supports. Note that these defaults may be overridden by other commands, by the setup script, by config files, or by the @@ -3742,7 +3742,7 @@ are just a bunch of \samp{self.foo = None} assignments. \end{methoddesc} -\begin{methoddesc}{finalize_options}{} +\begin{methoddesc}[Command]{finalize_options}{} Set final values for all the options that this command supports. This is always called as late as possible, ie. after any option assignments from the command-line or from other commands have been @@ -3751,7 +3751,7 @@ \var{bar} as long as \var{foo} still has the same value it was assigned in \method{initialize_options()}. \end{methoddesc} -\begin{methoddesc}{run}{} +\begin{methoddesc}[Command]{run}{} A command's raison d'etre: carry out the action it exists to perform, controlled by the options initialized in \method{initialize_options()}, customized by other commands, the setup From python-checkins at python.org Mon Apr 2 00:47:34 2007 From: python-checkins at python.org (georg.brandl) Date: Mon, 2 Apr 2007 00:47:34 +0200 (CEST) Subject: [Python-checkins] r54653 - python/trunk/Doc/lib/compiler.tex python/trunk/Doc/lib/email.tex python/trunk/Doc/lib/libwinreg.tex Message-ID: <20070401224734.D4CDD1E4007@bag.python.org> Author: georg.brandl Date: Mon Apr 2 00:47:31 2007 New Revision: 54653 Modified: python/trunk/Doc/lib/compiler.tex python/trunk/Doc/lib/email.tex python/trunk/Doc/lib/libwinreg.tex Log: Some semantic fixes. Modified: python/trunk/Doc/lib/compiler.tex ============================================================================== --- python/trunk/Doc/lib/compiler.tex (original) +++ python/trunk/Doc/lib/compiler.tex Mon Apr 2 00:47:31 2007 @@ -103,8 +103,7 @@ construct. The root of the tree is \class{Module} object. The abstract syntax offers a higher level interface to parsed Python -source code. The \ulink{\module{parser}} -{http://www.python.org/doc/current/lib/module-parser.html} +source code. The \refmodule{parser} module and the compiler written in C for the Python interpreter use a concrete syntax tree. The concrete syntax is tied closely to the grammar description used for the Python parser. Instead of a single Modified: python/trunk/Doc/lib/email.tex ============================================================================== --- python/trunk/Doc/lib/email.tex (original) +++ python/trunk/Doc/lib/email.tex Mon Apr 2 00:47:31 2007 @@ -239,7 +239,7 @@ The \module{email} package was originally prototyped as a separate library called -\ulink{\module{mimelib}}{http://mimelib.sf.net/}. +\ulink{\texttt{mimelib}}{http://mimelib.sf.net/}. Changes have been made so that method names are more consistent, and some methods or modules have either been added or removed. The semantics of some of the methods Modified: python/trunk/Doc/lib/libwinreg.tex ============================================================================== --- python/trunk/Doc/lib/libwinreg.tex (original) +++ python/trunk/Doc/lib/libwinreg.tex Mon Apr 2 00:47:31 2007 @@ -151,7 +151,7 @@ An application should only call \function{FlushKey()} if it requires absolute certainty that registry changes are on disk. - \emph{If you don't know whether a \function{FlushKey()} call is required, it + \note{If you don't know whether a \function{FlushKey()} call is required, it probably isn't.} \end{funcdesc} From python-checkins at python.org Mon Apr 2 01:29:12 2007 From: python-checkins at python.org (georg.brandl) Date: Mon, 2 Apr 2007 01:29:12 +0200 (CEST) Subject: [Python-checkins] r54654 - python/trunk/Doc/lib/liblogging.tex Message-ID: <20070401232912.E13551E4007@bag.python.org> Author: georg.brandl Date: Mon Apr 2 01:29:10 2007 New Revision: 54654 Modified: python/trunk/Doc/lib/liblogging.tex Log: Remove bogus entry. Modified: python/trunk/Doc/lib/liblogging.tex ============================================================================== --- python/trunk/Doc/lib/liblogging.tex (original) +++ python/trunk/Doc/lib/liblogging.tex Mon Apr 2 01:29:10 2007 @@ -1138,9 +1138,6 @@ Closes the socket. \end{methoddesc} -\begin{methoddesc}{handleError}{} -\end{methoddesc} - \begin{methoddesc}{emit}{} Pickles the record's attribute dictionary and writes it to the socket in binary format. If there is an error with the socket, silently drops the From python-checkins at python.org Mon Apr 2 01:31:33 2007 From: python-checkins at python.org (georg.brandl) Date: Mon, 2 Apr 2007 01:31:33 +0200 (CEST) Subject: [Python-checkins] r54655 - python/trunk/Doc/lib/libstdtypes.tex Message-ID: <20070401233133.B61AF1E4007@bag.python.org> Author: georg.brandl Date: Mon Apr 2 01:31:30 2007 New Revision: 54655 Modified: python/trunk/Doc/lib/libstdtypes.tex Log: Fix the class name of strings. Modified: python/trunk/Doc/lib/libstdtypes.tex ============================================================================== --- python/trunk/Doc/lib/libstdtypes.tex (original) +++ python/trunk/Doc/lib/libstdtypes.tex Mon Apr 2 01:31:30 2007 @@ -572,25 +572,25 @@ These are the string methods which both 8-bit strings and Unicode objects support: -\begin{methoddesc}[string]{capitalize}{} +\begin{methoddesc}[str]{capitalize}{} Return a copy of the string with only its first character capitalized. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{center}{width\optional{, fillchar}} +\begin{methoddesc}[str]{center}{width\optional{, fillchar}} Return centered in a string of length \var{width}. Padding is done using the specified \var{fillchar} (default is a space). \versionchanged[Support for the \var{fillchar} argument]{2.4} \end{methoddesc} -\begin{methoddesc}[string]{count}{sub\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{count}{sub\optional{, start\optional{, end}}} Return the number of occurrences of substring \var{sub} in string S\code{[\var{start}:\var{end}]}. Optional arguments \var{start} and \var{end} are interpreted as in slice notation. \end{methoddesc} -\begin{methoddesc}[string]{decode}{\optional{encoding\optional{, errors}}} +\begin{methoddesc}[str]{decode}{\optional{encoding\optional{, errors}}} Decodes the string using the codec registered for \var{encoding}. \var{encoding} defaults to the default string encoding. \var{errors} may be given to set a different error handling scheme. The default is @@ -602,7 +602,7 @@ \versionchanged[Support for other error handling schemes added]{2.3} \end{methoddesc} -\begin{methoddesc}[string]{encode}{\optional{encoding\optional{,errors}}} +\begin{methoddesc}[str]{encode}{\optional{encoding\optional{,errors}}} Return an encoded version of the string. Default encoding is the current default string encoding. \var{errors} may be given to set a different error handling scheme. The default for \var{errors} is @@ -617,7 +617,7 @@ \code{'backslashreplace'} and other error handling schemes added]{2.3} \end{methoddesc} -\begin{methoddesc}[string]{endswith}{suffix\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{endswith}{suffix\optional{, start\optional{, end}}} Return \code{True} if the string ends with the specified \var{suffix}, otherwise return \code{False}. \var{suffix} can also be a tuple of suffixes to look for. With optional \var{start}, test beginning at @@ -626,13 +626,13 @@ \versionchanged[Accept tuples as \var{suffix}]{2.5} \end{methoddesc} -\begin{methoddesc}[string]{expandtabs}{\optional{tabsize}} +\begin{methoddesc}[str]{expandtabs}{\optional{tabsize}} Return a copy of the string where all tab characters are expanded using spaces. If \var{tabsize} is not given, a tab size of \code{8} characters is assumed. \end{methoddesc} -\begin{methoddesc}[string]{find}{sub\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{find}{sub\optional{, start\optional{, end}}} Return the lowest index in the string where substring \var{sub} is found, such that \var{sub} is contained in the range [\var{start}, \var{end}]. Optional arguments \var{start} and \var{end} are @@ -640,47 +640,47 @@ not found. \end{methoddesc} -\begin{methoddesc}[string]{index}{sub\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{index}{sub\optional{, start\optional{, end}}} Like \method{find()}, but raise \exception{ValueError} when the substring is not found. \end{methoddesc} -\begin{methoddesc}[string]{isalnum}{} +\begin{methoddesc}[str]{isalnum}{} Return true if all characters in the string are alphanumeric and there is at least one character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{isalpha}{} +\begin{methoddesc}[str]{isalpha}{} Return true if all characters in the string are alphabetic and there is at least one character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{isdigit}{} +\begin{methoddesc}[str]{isdigit}{} Return true if all characters in the string are digits and there is at least one character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{islower}{} +\begin{methoddesc}[str]{islower}{} Return true if all cased characters in the string are lowercase and there is at least one cased character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{isspace}{} +\begin{methoddesc}[str]{isspace}{} Return true if there are only whitespace characters in the string and there is at least one character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{istitle}{} +\begin{methoddesc}[str]{istitle}{} Return true if the string is a titlecased string and there is at least one character, for example uppercase characters may only follow uncased characters and lowercase characters only cased ones. Return false @@ -689,20 +689,20 @@ For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{isupper}{} +\begin{methoddesc}[str]{isupper}{} Return true if all cased characters in the string are uppercase and there is at least one cased character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{join}{seq} +\begin{methoddesc}[str]{join}{seq} Return a string which is the concatenation of the strings in the sequence \var{seq}. The separator between elements is the string providing this method. \end{methoddesc} -\begin{methoddesc}[string]{ljust}{width\optional{, fillchar}} +\begin{methoddesc}[str]{ljust}{width\optional{, fillchar}} Return the string left justified in a string of length \var{width}. Padding is done using the specified \var{fillchar} (default is a space). The original string is returned if @@ -710,13 +710,13 @@ \versionchanged[Support for the \var{fillchar} argument]{2.4} \end{methoddesc} -\begin{methoddesc}[string]{lower}{} +\begin{methoddesc}[str]{lower}{} Return a copy of the string converted to lowercase. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{lstrip}{\optional{chars}} +\begin{methoddesc}[str]{lstrip}{\optional{chars}} Return a copy of the string with leading characters removed. The \var{chars} argument is a string specifying the set of characters to be removed. If omitted or \code{None}, the \var{chars} argument @@ -731,7 +731,7 @@ \versionchanged[Support for the \var{chars} argument]{2.2.2} \end{methoddesc} -\begin{methoddesc}[string]{partition}{sep} +\begin{methoddesc}[str]{partition}{sep} Split the string at the first occurrence of \var{sep}, and return a 3-tuple containing the part before the separator, the separator itself, and the part after the separator. If the separator is not @@ -740,26 +740,26 @@ \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}[string]{replace}{old, new\optional{, count}} +\begin{methoddesc}[str]{replace}{old, new\optional{, count}} Return a copy of the string with all occurrences of substring \var{old} replaced by \var{new}. If the optional argument \var{count} is given, only the first \var{count} occurrences are replaced. \end{methoddesc} -\begin{methoddesc}[string]{rfind}{sub \optional{,start \optional{,end}}} +\begin{methoddesc}[str]{rfind}{sub \optional{,start \optional{,end}}} Return the highest index in the string where substring \var{sub} is found, such that \var{sub} is contained within s[start,end]. Optional arguments \var{start} and \var{end} are interpreted as in slice notation. Return \code{-1} on failure. \end{methoddesc} -\begin{methoddesc}[string]{rindex}{sub\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{rindex}{sub\optional{, start\optional{, end}}} Like \method{rfind()} but raises \exception{ValueError} when the substring \var{sub} is not found. \end{methoddesc} -\begin{methoddesc}[string]{rjust}{width\optional{, fillchar}} +\begin{methoddesc}[str]{rjust}{width\optional{, fillchar}} Return the string right justified in a string of length \var{width}. Padding is done using the specified \var{fillchar} (default is a space). The original string is returned if @@ -767,7 +767,7 @@ \versionchanged[Support for the \var{fillchar} argument]{2.4} \end{methoddesc} -\begin{methoddesc}[string]{rpartition}{sep} +\begin{methoddesc}[str]{rpartition}{sep} Split the string at the last occurrence of \var{sep}, and return a 3-tuple containing the part before the separator, the separator itself, and the part after the separator. If the separator is not @@ -776,7 +776,7 @@ \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}[string]{rsplit}{\optional{sep \optional{,maxsplit}}} +\begin{methoddesc}[str]{rsplit}{\optional{sep \optional{,maxsplit}}} Return a list of the words in the string, using \var{sep} as the delimiter string. If \var{maxsplit} is given, at most \var{maxsplit} splits are done, the \emph{rightmost} ones. If \var{sep} is not specified @@ -786,7 +786,7 @@ \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}[string]{rstrip}{\optional{chars}} +\begin{methoddesc}[str]{rstrip}{\optional{chars}} Return a copy of the string with trailing characters removed. The \var{chars} argument is a string specifying the set of characters to be removed. If omitted or \code{None}, the \var{chars} argument @@ -801,7 +801,7 @@ \versionchanged[Support for the \var{chars} argument]{2.2.2} \end{methoddesc} -\begin{methoddesc}[string]{split}{\optional{sep \optional{,maxsplit}}} +\begin{methoddesc}[str]{split}{\optional{sep \optional{,maxsplit}}} Return a list of the words in the string, using \var{sep} as the delimiter string. If \var{maxsplit} is given, at most \var{maxsplit} splits are done. (thus, the list will have at most \code{\var{maxsplit}+1} @@ -824,13 +824,13 @@ returns an empty list. \end{methoddesc} -\begin{methoddesc}[string]{splitlines}{\optional{keepends}} +\begin{methoddesc}[str]{splitlines}{\optional{keepends}} Return a list of the lines in the string, breaking at line boundaries. Line breaks are not included in the resulting list unless \var{keepends} is given and true. \end{methoddesc} -\begin{methoddesc}[string]{startswith}{prefix\optional{, +\begin{methoddesc}[str]{startswith}{prefix\optional{, start\optional{, end}}} Return \code{True} if string starts with the \var{prefix}, otherwise return \code{False}. \var{prefix} can also be a tuple of @@ -841,7 +841,7 @@ \versionchanged[Accept tuples as \var{prefix}]{2.5} \end{methoddesc} -\begin{methoddesc}[string]{strip}{\optional{chars}} +\begin{methoddesc}[str]{strip}{\optional{chars}} Return a copy of the string with the leading and trailing characters removed. The \var{chars} argument is a string specifying the set of characters to be removed. If omitted or \code{None}, the \var{chars} @@ -856,21 +856,21 @@ \versionchanged[Support for the \var{chars} argument]{2.2.2} \end{methoddesc} -\begin{methoddesc}[string]{swapcase}{} +\begin{methoddesc}[str]{swapcase}{} Return a copy of the string with uppercase characters converted to lowercase and vice versa. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{title}{} +\begin{methoddesc}[str]{title}{} Return a titlecased version of the string: words start with uppercase characters, all remaining cased characters are lowercase. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{translate}{table\optional{, deletechars}} +\begin{methoddesc}[str]{translate}{table\optional{, deletechars}} Return a copy of the string where all characters occurring in the optional argument \var{deletechars} are removed, and the remaining characters have been mapped through the given translation table, which @@ -890,13 +890,13 @@ \module{encodings.cp1251} for an example). \end{methoddesc} -\begin{methoddesc}[string]{upper}{} +\begin{methoddesc}[str]{upper}{} Return a copy of the string converted to uppercase. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{zfill}{width} +\begin{methoddesc}[str]{zfill}{width} Return the numeric string left filled with zeros in a string of length \var{width}. The original string is returned if \var{width} is less than \code{len(\var{s})}. From buildbot at python.org Mon Apr 2 05:06:42 2007 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Apr 2007 03:06:42 +0000 Subject: [Python-checkins] buildbot warnings in x86 cygwin 2.5 Message-ID: <20070402030642.042DD1E400F@bag.python.org> The Buildbot has detected a new failure of x86 cygwin 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520cygwin%25202.5/builds/13 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: neal.norwitz Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From nnorwitz at gmail.com Mon Apr 2 11:31:09 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Mon, 2 Apr 2007 05:31:09 -0400 Subject: [Python-checkins] Python Regression Test Failures doc (1) Message-ID: <20070402093109.GA29567@python.psfb.org> TEXINPUTS=/home/neal/python/trunk/Doc/commontex: python /home/neal/python/trunk/Doc/tools/mkhowto --html --about html/stdabout.dat --iconserver ../icons --favicon ../icons/pyfav.png --address "See About this document... for information on suggesting changes." --up-link ../index.html --up-title "Python Documentation Index" --global-module-index "../modindex.html" --dvips-safe --dir html/lib lib/lib.tex *** Session transcript and error messages are in /home/neal/python/trunk/Doc/html/lib/lib.how. *** Exited with status 1. The relevant lines from the transcript are: ------------------------------------------------------------------------ +++ latex lib This is TeX, Version 3.14159 (Web2C 7.4.5) (/home/neal/python/trunk/Doc/lib/lib.tex LaTeX2e <2001/06/01> Babel and hyphenation patterns for american, french, german, ngerman, n ohyphenation, loaded. (/home/neal/python/trunk/Doc/texinputs/manual.cls Document Class: manual 1998/03/03 Document class (Python manual) (/home/neal/python/trunk/Doc/texinputs/pypaper.sty (/usr/share/texmf/tex/latex/psnfss/times.sty) Using Times instead of Computer Modern. ) (/usr/share/texmf/tex/latex/misc/fancybox.sty Style option: `fancybox' v1.3 <2000/09/19> (tvz) ) (/usr/share/texmf/tex/latex/base/report.cls Document Class: report 2001/04/21 v1.4e Standard LaTeX document class (/usr/share/texmf/tex/latex/base/size10.clo)) (/home/neal/python/trunk/Doc/texinputs/fancyhdr.sty) Using fancier footers than usual. (/home/neal/python/trunk/Doc/texinputs/fncychap.sty) Using fancy chapter headings. (/home/neal/python/trunk/Doc/texinputs/python.sty (/usr/share/texmf/tex/latex/tools/longtable.sty) (/home/neal/python/trunk/Doc/texinputs/underscore.sty) (/usr/share/texmf/tex/latex/tools/verbatim.sty) (/usr/share/texmf/tex/latex/base/alltt.sty))) (/home/neal/python/trunk/Doc/commontex/boilerplate.tex (/home/neal/python/trunk/Doc/commontex/patchlevel.tex)) Writing index file lib.idx No file lib.aux. (/usr/share/texmf/tex/latex/psnfss/ot1ptm.fd) (/usr/share/texmf/tex/latex/psnfss/ot1phv.fd) [1] (/home/neal/python/trunk/Doc/commontex/copyright.tex (/usr/share/texmf/tex/latex/psnfss/omsptm.fd)) [2] Adding blank page after the abstract. [1] [2] No file lib.toc. Adding blank page after the table of contents. [1] [2] (/home/neal/python/trunk/Doc/lib/libintro.tex Chapter 1. (/usr/share/texmf/tex/latex/psnfss/ot1pcr.fd) LaTeX Warning: Reference `builtin' on page 1 undefined on input line 49. ) (/home/neal/python/trunk/Doc/lib/libobjs.tex [1] [2] Chapter 2. ) (/home/neal/python/trunk/Doc/lib/libfuncs.tex [3] [4] [5] [6] [7] LaTeX Warning: Reference `bltin-file-objects' on page 8 undefined on input line 424. Underfull \hbox (badness 10000) in paragraph at lines 445--449 []\OT1/ptm/m/n/10 Note that \OT1/pcr/m/n/10 filter(function, \OT1/ptm/m/it/10 i t-er-able\OT1/pcr/m/n/10 ) \OT1/ptm/m/n/10 is equiv-a-lent to \OT1/pcr/m/n/10 [ item for item in \OT1/ptm/m/it/10 it-er-able \OT1/pcr/m/n/10 if [8] [9] [10] LaTeX Warning: Reference `bltin-file-objects' on page 11 undefined on input lin e 705. [11] [12] [13] [14] LaTeX Warning: Reference `typesseq-mutable' on page 15 undefined on input line 1050. [15] [16] [17]) (/home/neal/python/trunk/Doc/lib/libexcs.tex Underfull \hbox (badness 10000) in paragraph at lines 78--82 \OT1/ptm/m/n/10 The base class for all built-in ex-cep-tions ex-cept \OT1/pcr/m /n/10 StopIteration\OT1/ptm/m/n/10 , \OT1/pcr/m/n/10 GeneratorExit\OT1/ptm/m/n/ 10 , [18] [19] [20] [21] No file ../../Lib/test/exception_hierarchy.txt. ) (/home/neal/python/trunk/Doc/lib/libconsts.tex) (/home/neal/python/trunk/Doc/lib/libstdtypes.tex [22] Chapter 3. [23] [24] LaTeX Warning: Reference `built-in-funcs' on page 25 undefined on input line 29 5. [25] [26] [27] [28] LaTeX Warning: Reference `codec-base-classes' on page 29 undefined on input lin e 600. LaTeX Warning: Reference `codec-base-classes' on page 29 undefined on input lin e 613. LaTeX Warning: Reference `standard-encodings' on page 29 undefined on input lin e 614. [29] [30] [31] [32] Overfull \hbox (8.48134pt too wide) in paragraph at lines 977--987 [] Overfull \hbox (141.78873pt too wide) in paragraph at lines 994--1019 [] [33] Overfull \hbox (44.61931pt too wide) in paragraph at lines 1103--1135 [] [34] [35] [36] Overfull \hbox (98.60141pt too wide) in paragraph at lines 1315--1343 [] Overfull \hbox (44.38484pt too wide) in paragraph at lines 1405--1461 [] [37] [38] LaTeX Warning: Reference `built-in-funcs' on page 39 undefined on input line 15 31. LaTeX Warning: Reference `context-closing' on page 39 undefined on input line 1 583. [39] [40] [41] Underfull \hbox (badness 10000) in paragraph at lines 1836--1843 []\OT1/ptm/m/n/10 An ex-am-ple of a con-text man-ager that re-turns a re-lated ob-ject is the one re-turned by [42] [43] [44]) (/home/neal/python/trunk/Doc/lib/libstrings.tex [45] [46] Chapter 4. LaTeX Warning: Reference `string-methods' on page 47 undefined on input line 10 . ) (/home/neal/python/trunk/Doc/lib/libstring.tex [47] [48] [49] LaTeX Warning: Reference `string-methods' on page 50 undefined on input line 23 7. [50] [51]) (/home/neal/python/trunk/Doc/lib/libre.tex [52] [53] [54] [55] [56] [57] [58] [59] [60] [61]) (/home/neal/python/trunk/Doc/lib/libstruct.tex [62] [63] [64] LaTeX Warning: Reference `module-array' on page 65 undefined on input line 227. LaTeX Warning: Reference `module-xdrlib' on page 65 undefined on input line 228 . ) (/home/neal/python/trunk/Doc/lib/libdifflib.tex [65] [66] [67] [68] [69] [70] [71] [72]) (/home/neal/python/trunk/Doc/lib/libstringio.tex [73] LaTeX Warning: Reference `bltin-file-objects' on page 74 undefined on input lin e 11. [74]) (/home/neal/python/trunk/Doc/lib/libtextwrap.tex [75] [76]) (/home/neal/python/trunk/Doc/lib/libcodecs.tex [77] Underfull \hbox (badness 5161) in paragraph at lines 52--56 []\OT1/ptm/m/n/10 The fac-tory func-tions must re-turn ob-jects pro-vid-ing the in-ter-faces de-fined by the base classes [78] [79] Overfull \hbox (405.07822pt too wide) in paragraph at lines 288--300 [] [80] [81] [82] [83] [84] [85] [86] Overfull \hbox (11.18082pt too wide) in alignment at lines 820--901 [] [] [] Overfull \hbox (11.18082pt too wide) in alignment at lines 901--981 [] [] [] Overfull \hbox (254.7505pt too wide) in alignment at lines 981--1062 [] [] [] Overfull \hbox (254.7505pt too wide) in alignment at lines 1062--1142 [] [] [] [87] Overfull \hbox (254.7505pt too wide) in alignment at lines 1142--1167 [] [] [] Package longtable Warning: Column widths have changed (longtable) in table 4.1 on input line 1167. Overfull \hbox (465.03658pt too wide) in paragraph at lines 1179--1268 [] [88] [89]) (/home/neal/python/trunk/Doc/lib/libunicodedata.tex [90]) (/home/neal/python/trunk/Doc/lib/libstringprep.tex [91] [92]) (/home/neal/python/trunk/Doc/lib/libfpformat.tex) Underfull \hbox (badness 10000) in paragraph at lines 50--98 (/home/neal/python/trunk/Doc/lib/datatypes.tex [93] [94] Chapter 5. ) (/home/neal/python/trunk/Doc/lib/libdatetime.tex LaTeX Warning: Reference `module-calendar' on page 95 undefined on input line 5 6. LaTeX Warning: Reference `module-time' on page 95 undefined on input line 57. [95] [96] Underfull \hbox (badness 10000) in paragraph at lines 185--187 \OT1/ptm/m/n/10 The small-est pos-si-ble dif-fer-ence be-tween non-equal \OT1/p cr/m/n/10 timedelta \OT1/ptm/m/n/10 ob-jects, (/usr/share/texmf/tex/latex/psnfss/omlptm.fd) Overfull \hbox (44.65097pt too wide) in paragraph at lines 204--235 [] [97] [98] Underfull \hbox (badness 10000) in paragraph at lines 430--439 \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .month, \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .da y, 0, 0, 0, \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .weekday(), \OT1/ptm/m/it/10 d\OT 1/pcr/m/n/10 .toordinal() - date(\OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .year, 1, [99] Underfull \hbox (badness 10000) in paragraph at lines 464--467 []\OT1/ptm/m/n/10 The ISO cal-en-dar is a widely used vari-ant of the Gre-go-ri an cal-en-dar. See LaTeX Warning: Reference `strftime-behavior' on page 100 undefined on input lin e 507. [100] Underfull \hbox (badness 10000) in paragraph at lines 547--551 \OT1/ptm/m/n/10 Return the cur-rent lo-cal date-time, with \OT1/pcr/m/n/10 tzin fo None\OT1/ptm/m/n/10 . This is equiv-a-lent to Underfull \hbox (badness 10000) in paragraph at lines 561--566 []\OT1/ptm/m/n/10 Else \OT1/ptm/m/it/10 tz \OT1/ptm/m/n/10 must be an in-stance of a class \OT1/pcr/m/n/10 tzinfo \OT1/ptm/m/n/10 sub-class, and the cur-rent date Underfull \hbox (badness 10000) in paragraph at lines 561--566 \OT1/ptm/m/n/10 and time are con-verted to \OT1/ptm/m/it/10 tz\OT1/ptm/m/n/10 ' s time zone. In this case the re-sult is equiv-a-lent to Underfull \hbox (badness 10000) in paragraph at lines 582--586 []\OT1/ptm/m/n/10 Else \OT1/ptm/m/it/10 tz \OT1/ptm/m/n/10 must be an in-stance of a class \OT1/pcr/m/n/10 tzinfo \OT1/ptm/m/n/10 sub-class, and the times- Underfull \hbox (badness 10000) in paragraph at lines 582--586 \OT1/ptm/m/n/10 tamp is con-verted to \OT1/ptm/m/it/10 tz\OT1/ptm/m/n/10 's tim e zone. In this case the re-sult is equiv-a-lent to [101] Underfull \hbox (badness 5519) in paragraph at lines 646--648 \OT1/ptm/m/n/10 The lat-est rep-re-sentable \OT1/pcr/m/n/10 datetime\OT1/ptm/m/ n/10 , \OT1/pcr/m/n/10 datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, [102] [103] Underfull \hbox (badness 10000) in paragraph at lines 874--888 \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .weekday(), \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .toordinal() - date(\OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .year, 1, 1).toordinal() + 1, dst)) \OT1/ptm/m/n/10 The Underfull \hbox (badness 10000) in paragraph at lines 923--925 \OT1/ptm/m/n/10 Return a 3-tuple, (ISO year, ISO week num-ber, ISO week-day). T he same as [104] Underfull \hbox (badness 5064) in paragraph at lines 960--969 \OT1/ptm/m/n/10 Return a string rep-re-sent-ing the date and time, for ex-am-pl e \OT1/pcr/m/n/10 datetime(2002, 12, 4, 20, Underfull \hbox (badness 10000) in paragraph at lines 960--969 \OT1/pcr/m/n/10 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'\OT1/ptm/m/n/10 . \ OT1/pcr/m/n/10 d.ctime() \OT1/ptm/m/n/10 is equiv-a-lent to LaTeX Warning: Reference `strftime-behavior' on page 105 undefined on input lin e 973. [105] LaTeX Warning: Reference `strftime-behavior' on page 106 undefined on input lin e 1103. [106] [107] [108] [109] [110] [111]) (/home/neal/python/trunk/Doc/lib/libcalendar.tex [112] [113] [114] LaTeX Warning: Reference `module-datetime' on page 115 undefined on input line 302. LaTeX Warning: Reference `module-time' on page 115 undefined on input line 303. ) (/home/neal/python/trunk/Doc/lib/libcollections.tex [115] [116] [117] [118] [119] Overfull \hbox (6.89723pt too wide) in paragraph at lines 343--343 []\OT1/pcr/m/n/9 >>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('r ed', 1), ('blue', 4)][] [120] Overfull \hbox (4.8973pt too wide) in paragraph at lines 376--376 []\OT1/pcr/m/n/9 >>> p = Point(11, y=22) # instantiate with positional or k eyword arguments[] Overfull \hbox (31.89726pt too wide) in paragraph at lines 389--389 []\OT1/pcr/m/n/9 EmployeeRecord = NamedTuple('EmployeeRecord', 'name age title department paygrade')[] ) (/home/neal/python/trunk/Doc/lib/libheapq.tex [121] [122] [123]) (/home/neal/python/trunk/Doc/lib/libbisect.tex) (/home/neal/python/trunk/Doc/lib/libarray.tex [124] [125] [126] LaTeX Warning: Reference `module-struct' on page 127 undefined on input line 23 0. LaTeX Warning: Reference `module-xdrlib' on page 127 undefined on input line 23 3. [127]) (/home/neal/python/trunk/Doc/lib/libsets.tex LaTeX Warning: Reference `immutable-transforms' on page 128 undefined on input line 51. LaTeX Warning: Reference `immutable-transforms' on page 128 undefined on input line 59. [128] Overfull \hbox (98.60141pt too wide) in paragraph at lines 137--165 [] [129] [130]) (/home/neal/python/trunk/Doc/lib/libsched.tex [131]) (/home/neal/python/trunk/Doc/lib/libmutex.tex [132]) (/home/neal/python/trunk/Doc/lib/libqueue.tex [133]) (/home/neal/python/trunk/Doc/lib/libweakref.tex [134] [135] [136] [137]) (/home/neal/python/trunk/Doc/lib/libuserdict.tex [138] LaTeX Warning: Reference `typesmapping' on page 139 undefined on input line 40. LaTeX Warning: Reference `typesseq' on page 139 undefined on input line 97. [139] LaTeX Warning: Reference `string-methods' on page 140 undefined on input line 1 74. ) (/home/neal/python/trunk/Doc/lib/libtypes.tex [140] [141] Underfull \hbox (badness 10000) in paragraph at lines 200--205 \OT1/ptm/m/n/10 The type of ob-jects de-fined in ex-ten-sion mod-ules with \OT1 /pcr/m/n/10 PyMemberDef\OT1/ptm/m/n/10 , such as [142]) (/home/neal/python/trunk/Doc/lib/libnew.tex) (/home/neal/python/trunk/Doc/lib/libcopy.tex [143] LaTeX Warning: Reference `module-pickle' on page 144 undefined on input line 96 . ) (/home/neal/python/trunk/Doc/lib/libpprint.tex [144] [145] [146]) (/home/neal/python/trunk/Doc/lib/librepr.tex [147]) Underfull \hbox (badness 10000) in paragraph at lines 120--121 (/home/neal/python/trunk/Doc/lib/numeric.tex [148] Chapter 6. ) (/home/neal/python/trunk/Doc/lib/libmath.tex [149] [150] LaTeX Warning: Reference `module-cmath' on page 151 undefined on input line 208 . ) (/home/neal/python/trunk/Doc/lib/libcmath.tex [151] [152]) (/home/neal/python/trunk/Doc/lib/libdecimal.tex [153] [154] [155] [156] Overfull \hbox (21.09727pt too wide) in paragraph at lines 305--305 [] \OT1/pcr/m/n/9 digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6 ' | '7' | '8' | '9'[] [157] [158] [159] [160] [161] [162] [163] [164] [165] Overfull \vbox (959.57pt too high) has occurred while \output is active [166] [167] [168]) (/home/neal/python/trunk/Doc/lib/librandom.tex [169] Underfull \hbox (badness 6575) in paragraph at lines 119--124 \OT1/ptm/m/n/10 Return a ran-domly se-lected el-e-ment from \OT1/pcr/m/n/10 ran ge(\OT1/ptm/m/it/10 start\OT1/pcr/m/n/10 , \OT1/ptm/m/it/10 stop\OT1/pcr/m/n/10 , \OT1/ptm/m/it/10 step\OT1/pcr/m/n/10 )\OT1/ptm/m/n/10 . This is equiv-a-lent to [170] [171]) (/home/neal/python/trunk/Doc/lib/libitertools.tex [172] [173] [174] [175] Overfull \hbox (15.69728pt too wide) in paragraph at lines 323--323 [] \OT1/pcr/m/n/9 yield counter() # yields the fillvalue, or raises IndexError[] [176] [177] [178] [179]) (/home/neal/python/trunk/Doc/lib/libfunctools.tex [180] Overfull \vbox (255.57pt too high) has occurred while \output is active [181] [182]) (/home/neal/python/trunk/Doc/lib/liboperator.tex [183] [184] [185] [186] [187] [188]) (/home/neal/python/trunk/Doc/lib/netdata.tex [189] [190] Chapter 7. ) (/home/neal/python/trunk/Doc/lib/email.tex LaTeX Warning: Reference `module-smtplib' on page 191 undefined on input line 5 8. LaTeX Warning: Reference `module-nntplib' on page 191 undefined on input line 5 9. (/home/neal/python/trunk/Doc/lib/emailmessage.tex [191] [192] [193] [194] [195] [196]) (/home/neal/python/trunk/Doc/lib/emailparser.tex [197] [198] [199]) (/home/neal/python/trunk/Doc/lib/emailgenerator.tex [200]) (/home/neal/python/trunk/Doc/lib/emailmimebase.tex [201] [202]) (/home/neal/python/trunk/Doc/lib/emailheaders.tex [203] [204]) (/home/neal/python/trunk/Doc/lib/emailcharsets.tex [205] [206]) (/home/neal/python/trunk/Doc/lib/emailencoders.tex [207]) (/home/neal/python/trunk/Doc/lib/emailexc.tex [208]) (/home/neal/python/trunk/Doc/lib/emailutil.tex [209] [210]) (/home/neal/python/trunk/Doc/lib/emailiter.tex [211]) [212] [213] [214] [215] [216] [217] [218]) (/home/neal/python/trunk/Doc/lib/libmailcap.tex [219]) (/home/neal/python/trunk/Doc/lib/libmailbox.tex [220] LaTeX Warning: Reference `module-email' on page 221 undefined on input line 18. Underfull \hbox (badness 10000) in paragraph at lines 72--73 [221] [222] [223] [224] [225] [226] (/usr/share/texmf/tex/latex/psnfss/omspcr.fd) [227] [228] [229] [230] [231] [232] [233] [234] [235] [236] [237]) (/home/neal/python/trunk/Doc/lib/libmhlib.tex [238] [239] [240]) (/home/neal/python/trunk/Doc/lib/libmimetools.tex [241] LaTeX Warning: Reference `module-email' on page 242 undefined on input line 61. LaTeX Warning: Reference `module-rfc822' on page 242 undefined on input line 63 . LaTeX Warning: Reference `module-multifile' on page 242 undefined on input line 65. ) (/home/neal/python/trunk/Doc/lib/libmimetypes.tex [242] [243] [244]) (/home/neal/python/trunk/Doc/lib/libmimewriter.tex [245]) (/home/neal/python/trunk/Doc/lib/libmimify.tex [246] LaTeX Warning: Reference `module-quopri' on page 247 undefined on input line 93 . ) (/home/neal/python/trunk/Doc/lib/libmultifile.tex LaTeX Warning: Reference `module-email' on page 247 undefined on input line 43. [247]) (/home/neal/python/trunk/Doc/lib/librfc822.tex [248] [249] LaTeX Warning: Reference `module-email' on page 250 undefined on input line 133 . LaTeX Warning: Reference `module-mailbox' on page 250 undefined on input line 1 35. [250] LaTeX Warning: Reference `module-mimetools' on page 251 undefined on input line 137. [251] Underfull \hbox (badness 7379) in paragraph at lines 254--270 []\OT1/pcr/m/n/10 Message \OT1/ptm/m/n/10 in-stances also sup-port a lim-ited m ap-ping in-ter-face. In par-tic-u-lar: \OT1/ptm/m/it/10 m\OT1/pcr/m/n/10 [name] \OT1/ptm/m/n/10 is like [252]) (/home/neal/python/trunk/Doc/lib/libbase64.tex [253] LaTeX Warning: Reference `module-binascii' on page 254 undefined on input line 163. [254]) (/home/neal/python/trunk/Doc/lib/libbinhex.tex LaTeX Warning: Reference `module-binascii' on page 255 undefined on input line 41. ) (/home/neal/python/trunk/Doc/lib/libbinascii.tex [255] [256] LaTeX Warning: Reference `module-base64' on page 257 undefined on input line 14 0. LaTeX Warning: Reference `module-binhex' on page 257 undefined on input line 14 2. LaTeX Warning: Reference `module-uu' on page 257 undefined on input line 144. LaTeX Warning: Reference `module-quopri' on page 257 undefined on input line 14 6. ) (/home/neal/python/trunk/Doc/lib/libquopri.tex LaTeX Warning: Reference `module-mimify' on page 257 undefined on input line 59 . LaTeX Warning: Reference `module-base64' on page 257 undefined on input line 60 . [257]) (/home/neal/python/trunk/Doc/lib/libuu.tex LaTeX Warning: Reference `module-binascii' on page 258 undefined on input line 57. ) (/home/neal/python/trunk/Doc/lib/markup.tex [258] Chapter 8. ) (/home/neal/python/trunk/Doc/lib/libhtmlparser.tex [259] [260]) (/home/neal/python/trunk/Doc/lib/libsgmllib.tex [261] [262] [263]) (/home/neal/python/trunk/Doc/lib/libhtmllib.tex LaTeX Warning: Reference `module-formatter' on page 264 undefined on input line 81. LaTeX Warning: Reference `module-HTMLParser' on page 264 undefined on input lin e 87. [264] LaTeX Warning: Reference `module-htmlentitydefs' on page 265 undefined on input line 89. LaTeX Warning: Reference `module-sgmllib' on page 265 undefined on input line 9 0. Underfull \hbox (badness 7168) in paragraph at lines 158--165 \OT1/ptm/m/n/10 This mod-ule de-fines three dic-tio-nar-ies, \OT1/pcr/m/n/10 na me2codepoint\OT1/ptm/m/n/10 , \OT1/pcr/m/n/10 codepoint2name\OT1/ptm/m/n/10 , a nd \OT1/pcr/m/n/10 entitydefs\OT1/ptm/m/n/10 . [265]) (/home/neal/python/trunk/Doc/lib/libpyexpat.tex LaTeX Warning: Reference `expaterror-objects' on page 266 undefined on input li ne 36. [266] Underfull \hbox (badness 10000) in paragraph at lines 160--167 \OT1/ptm/m/n/10 Calling this with a true value for \OT1/ptm/m/it/10 flag \OT1/p tm/m/n/10 (the de-fault) will cause Ex-pat to call the [267] [268] [269] [270] [271] [272] [273]) (/home/neal/python/trunk/Doc/lib/xmldom.tex LaTeX Warning: Reference `dom-conformance' on page 274 undefined on input line 71. [274] [275] LaTeX Warning: Reference `dom-implementation-objects' on page 276 undefined on input line 181. LaTeX Warning: Reference `dom-node-objects' on page 276 undefined on input line 183. LaTeX Warning: Reference `dom-nodelist-objects' on page 276 undefined on input line 185. LaTeX Warning: Reference `dom-documenttype-objects' on page 276 undefined on in put line 187. LaTeX Warning: Reference `dom-document-objects' on page 276 undefined on input line 189. LaTeX Warning: Reference `dom-element-objects' on page 276 undefined on input l ine 191. LaTeX Warning: Reference `dom-attr-objects' on page 276 undefined on input line 193. LaTeX Warning: Reference `dom-comment-objects' on page 276 undefined on input l ine 195. LaTeX Warning: Reference `dom-text-objects' on page 276 undefined on input line 197. LaTeX Warning: Reference `dom-pi-objects' on page 276 undefined on input line 1 99. [276] [277] [278] [279] [280] [281] Underfull \hbox (badness 10000) in paragraph at lines 807--810 \OT1/ptm/m/n/10 Exception when a node does not ex-ist in the ref-er-enced con-t ext. For ex-am-ple, [282] [283]) (/home/neal/python/trunk/Doc/lib/xmldomminidom.tex [284] [285] [286] [287] Underfull \hbox (badness 10000) in paragraph at lines 242--246 []\OT1/pcr/m/n/10 const \OT1/ptm/m/n/10 dec-la-ra-tions map to vari-ables in th eir re-spec-tive scope (e.g. ) (/home/neal/python/trunk/Doc/lib/xmldompulldom.tex [288]) (/home/neal/python/trunk/Doc/lib/xmlsax.tex [289] LaTeX Warning: Reference `module-xml.sax.handler' on page 290 undefined on inpu t line 122. LaTeX Warning: Reference `module-xml.sax.saxutils' on page 290 undefined on inp ut line 125. LaTeX Warning: Reference `module-xml.sax.xmlreader' on page 290 undefined on in put line 128. [290]) (/home/neal/python/trunk/Doc/lib/xmlsaxhandler.tex [291] [292] [293] [294]) (/home/neal/python/trunk/Doc/lib/xmlsaxutils.tex [295]) (/home/neal/python/trunk/Doc/lib/xmlsaxreader.tex [296] LaTeX Warning: Reference `attributes-objects' on page 297 undefined on input li ne 74. LaTeX Warning: Reference `attributes-ns-objects' on page 297 undefined on input line 92. [297] Underfull \hbox (badness 10000) in paragraph at lines 159--163 \OT1/ptm/m/n/10 Return the cur-rent set-ting for fea-ture \OT1/ptm/m/it/10 fea- ture-name\OT1/ptm/m/n/10 . If the fea-ture is not rec-og-nized, Underfull \hbox (badness 6188) in paragraph at lines 173--177 \OT1/ptm/m/n/10 Return the cur-rent set-ting for prop-erty \OT1/ptm/m/it/10 pro p-er-ty-name\OT1/ptm/m/n/10 . If the prop-erty is not rec-og-nized, a [298] LaTeX Warning: Reference `attributes-objects' on page 299 undefined on input li ne 330. [299]) (/home/neal/python/trunk/Doc/lib/libetree.tex [300] [301] [302] [303]) (/home/neal/python/trunk/Doc/lib/fileformats.tex [304] Chapter 9. ) (/home/neal/python/trunk/Doc/lib/libcsv.tex LaTeX Warning: Reference `csv-examples' on page 305 undefined on input line 37. LaTeX Warning: Reference `csv-fmt-params' on page 305 undefined on input line 6 8. [305] LaTeX Warning: Reference `csv-fmt-params' on page 306 undefined on input line 1 01. LaTeX Warning: Reference `csv-fmt-params' on page 306 undefined on input line 1 17. [306] [307] LaTeX Warning: Reference `csv-contents' on page 308 undefined on input line 320 . [308] [309]) (/home/neal/python/trunk/Doc/lib/libcfgparser.tex [310] Overfull \vbox (35.57pt too high) has occurred while \output is active [311] Underfull \hbox (badness 10000) in paragraph at lines 22--23 [312] LaTeX Warning: Reference `module-shlex' on page 313 undefined on input line 150 . [313] [314]) (/home/neal/python/trunk/Doc/lib/librobotparser.tex Overfull \hbox (1.49724pt too wide) in paragraph at lines 66--66 []\OT1/pcr/m/n/9 >>> rp.can_fetch("*", "http://www.musi-cal.com/cgi-bin/search? city=San+Francisco")[] ) (/home/neal/python/trunk/Doc/lib/libnetrc.tex [315]) (/home/neal/python/trunk/Doc/lib/libxdrlib.tex [316] [317] [318]) Underfull \hbox (badness 10000) in paragraph at lines 244--183 (/home/neal/python/trunk/Doc/lib/libcrypto.tex [319] [320] Chapter 10. ) (/home/neal/python/trunk/Doc/lib/libhashlib.tex [321] LaTeX Warning: Reference `module-hmac' on page 322 undefined on input line 107. LaTeX Warning: Reference `module-base64' on page 322 undefined on input line 10 8. ) (/home/neal/python/trunk/Doc/lib/libhmac.tex [322] LaTeX Warning: Reference `module-hashlib' on page 323 undefined on input line 5 3. ) (/home/neal/python/trunk/Doc/lib/libmd5.tex [323] LaTeX Warning: Reference `module-sha' on page 324 undefined on input line 91. ) (/home/neal/python/trunk/Doc/lib/libsha.tex [324]) (/home/neal/python/trunk/Doc/lib/filesys.tex [325] [326] Chapter 11. LaTeX Warning: Reference `bltin-file-objects' on page 327 undefined on input li ne 12. LaTeX Warning: Reference `module-os' on page 327 undefined on input line 17. ) (/home/neal/python/trunk/Doc/lib/libposixpath.tex [327] (/usr/share/texmf/tex/latex/psnfss/omsphv.fd) [328] [329]) (/home/neal/python/trunk/Doc/lib/libfileinput.tex [330] [331] Underfull \hbox (badness 10000) in paragraph at lines 185--187 []\OT1/ptm/m/n/10 Usage ex-am-ple: `\OT1/pcr/m/n/10 fi = fileinput.FileInput(op enhook=fileinput.hook_- ) (/home/neal/python/trunk/Doc/lib/libstat.tex [332]) (/home/neal/python/trunk/Doc/lib/libstatvfs.tex [333] [334]) (/home/neal/python/trunk/Doc/lib/libfilecmp.tex [335]) (/home/neal/python/trunk/Doc/lib/libtempfile.tex [336] [337]) (/home/neal/python/trunk/Doc/lib/libglob.tex [338] LaTeX Warning: Reference `module-fnmatch' on page 339 undefined on input line 5 0. ) (/home/neal/python/trunk/Doc/lib/libfnmatch.tex [339] LaTeX Warning: Reference `module-glob' on page 340 undefined on input line 85. ) (/home/neal/python/trunk/Doc/lib/liblinecache.tex) (/home/neal/python/trunk/Doc/lib/libshutil.tex [340] [341]) (/home/neal/python/trunk/Doc/lib/libdircache.tex) Underfull \hbox (badness 10000) in paragraph at lines 37--206 [342] (/home/neal/python/trunk/Doc/lib/archiving.tex [343] [344] Chapter 12. ) (/home/neal/python/trunk/Doc/lib/libzlib.tex [345] [346] LaTeX Warning: Reference `module-gzip' on page 347 undefined on input line 193. ) (/home/neal/python/trunk/Doc/lib/libgzip.tex [347] LaTeX Warning: Reference `module-zlib' on page 348 undefined on input line 69. ) (/home/neal/python/trunk/Doc/lib/libbz2.tex Underfull \hbox (badness 5460) in paragraph at lines 19--22 []\OT1/pcr/m/n/10 BZ2File \OT1/ptm/m/n/10 class im-ple-ments a com-plete file i n-ter-face, in-clud-ing \OT1/pcr/m/n/10 readline()\OT1/ptm/m/n/10 , \OT1/pcr/m/ n/10 readlines()\OT1/ptm/m/n/10 , [348] [349]) (/home/neal/python/trunk/Doc/lib/libzipfile.tex LaTeX Warning: Reference `zipfile-objects' on page 350 undefined on input line 38. LaTeX Warning: Reference `zipinfo-objects' on page 350 undefined on input line 55. [350] [351] [352] [353]) (/home/neal/python/trunk/Doc/lib/libtarfile.tex LaTeX Warning: Reference `tarfile-objects' on page 354 undefined on input line 32. LaTeX Warning: Reference `tar-examples' on page 354 undefined on input line 69. [354] LaTeX Warning: Reference `tarfile-objects' on page 355 undefined on input line 85. LaTeX Warning: Reference `module-zipfile' on page 355 undefined on input line 1 63. [355] LaTeX Warning: Reference `tarinfo-objects' on page 356 undefined on input line 181. Underfull \hbox (badness 5878) in paragraph at lines 234--241 []\OT1/ptm/m/n/10 The \OT1/ptm/m/it/10 en-cod-ing \OT1/ptm/m/n/10 ar-gu-ment de -fines the lo-cal char-ac-ter en-cod-ing. It de-faults to the value from LaTeX Warning: Reference `module-tarfile' on page 356 undefined on input line 2 51. [356] [357] [358] [359]) Underfull \hbox (badness 10000) in paragraph at lines 549--214 (/home/neal/python/trunk/Doc/lib/persistence.tex [360] Chapter 13. ) (/home/neal/python/trunk/Doc/lib/libpickle.tex [361] Underfull \hbox (badness 10000) in paragraph at lines 94--95 [362] LaTeX Warning: Reference `pickle-sub' on page 363 undefined on input line 255. [363] LaTeX Warning: Reference `pickle-protocol' on page 364 undefined on input line 347. [364] LaTeX Warning: Reference `pickle-protocol' on page 365 undefined on input line 377. LaTeX Warning: Reference `pickle-sub' on page 365 undefined on input line 433. [365] Underfull \hbox (badness 10000) in paragraph at lines 495--496 [366] LaTeX Warning: Reference `pickle-inst' on page 367 undefined on input line 536. [367] [368] [369] [370] LaTeX Warning: Reference `module-copyreg' on page 371 undefined on input line 8 40. LaTeX Warning: Reference `module-shelve' on page 371 undefined on input line 84 2. LaTeX Warning: Reference `module-copy' on page 371 undefined on input line 844. LaTeX Warning: Reference `module-marshal' on page 371 undefined on input line 8 46. ) (/home/neal/python/trunk/Doc/lib/libcopyreg.tex [371]) (/home/neal/python/trunk/Doc/lib/libshelve.tex [372] [373] LaTeX Warning: Reference `module-anydbm' on page 374 undefined on input line 16 5. LaTeX Warning: Reference `module-bsddb' on page 374 undefined on input line 166 . LaTeX Warning: Reference `module-dbhash' on page 374 undefined on input line 16 8. LaTeX Warning: Reference `module-dbm' on page 374 undefined on input line 169. LaTeX Warning: Reference `module-dumbdbm' on page 374 undefined on input line 1 70. LaTeX Warning: Reference `module-gdbm' on page 374 undefined on input line 171. LaTeX Warning: Reference `module-pickle' on page 374 undefined on input line 17 2. LaTeX Warning: Reference `module-cPickle' on page 374 undefined on input line 1 73. ) (/home/neal/python/trunk/Doc/lib/libmarshal.tex [374] Underfull \hbox (badness 10000) in paragraph at lines 38--39 [375]) (/home/neal/python/trunk/Doc/lib/libanydbm.tex [376] LaTeX Warning: Reference `module-dbhash' on page 377 undefined on input line 77 . LaTeX Warning: Reference `module-dbm' on page 377 undefined on input line 78. LaTeX Warning: Reference `module-dumbdbm' on page 377 undefined on input line 7 9. LaTeX Warning: Reference `module-gdbm' on page 377 undefined on input line 80. LaTeX Warning: Reference `module-shelve' on page 377 undefined on input line 82 . LaTeX Warning: Reference `module-whichdb' on page 377 undefined on input line 8 4. ) (/home/neal/python/trunk/Doc/lib/libwhichdb.tex) (/home/neal/python/trunk/Doc/lib/libdbm.tex [377] LaTeX Warning: Reference `module-anydbm' on page 378 undefined on input line 57 . LaTeX Warning: Reference `module-gdbm' on page 378 undefined on input line 58. LaTeX Warning: Reference `module-whichdb' on page 378 undefined on input line 6 0. ) (/home/neal/python/trunk/Doc/lib/libgdbm.tex [378] LaTeX Warning: Reference `module-anydbm' on page 379 undefined on input line 97 . LaTeX Warning: Reference `module-whichdb' on page 379 undefined on input line 9 9. ) (/home/neal/python/trunk/Doc/lib/libdbhash.tex [379] LaTeX Warning: Reference `module-anydbm' on page 380 undefined on input line 43 . LaTeX Warning: Reference `module-bsddb' on page 380 undefined on input line 44. LaTeX Warning: Reference `module-whichdb' on page 380 undefined on input line 4 6. ) (/home/neal/python/trunk/Doc/lib/libbsddb.tex [380] LaTeX Warning: Reference `module-dbhash' on page 381 undefined on input line 10 6. [381]) (/home/neal/python/trunk/Doc/lib/libdumbdbm.tex [382] [383] LaTeX Warning: Reference `module-anydbm' on page 384 undefined on input line 46 . LaTeX Warning: Reference `module-dbm' on page 384 undefined on input line 47. LaTeX Warning: Reference `module-gdbm' on page 384 undefined on input line 48. LaTeX Warning: Reference `module-shelve' on page 384 undefined on input line 49 . LaTeX Warning: Reference `module-whichdb' on page 384 undefined on input line 5 1. ) (/home/neal/python/trunk/Doc/lib/libsqlite3.tex [384] [385] LaTeX Warning: Reference `sqlite3-Connection-IsolationLevel' on page 386 undefi ned on input line 150. LaTeX Warning: Reference `sqlite3-Types' on page 386 undefined on input line 16 6. [386] No file sqlite3/complete_statement.py. LaTeX Warning: Reference `sqlite3-Controlling-Transactions' on page 387 undefin ed on input line 216. [387] No file sqlite3/collation_reverse.py. [388] No file sqlite3/row_factory.py. No file sqlite3/text_factory.py. No file sqlite3/execute_1.py. No file sqlite3/execute_2.py. [389] No file sqlite3/executemany_1.py. No file sqlite3/executemany_2.py. [390] No file sqlite3/adapter_point_1.py. [391] No file sqlite3/adapter_point_2.py. Underfull \hbox (badness 10000) in paragraph at lines 518--522 []\OT1/ptm/m/n/10 The \OT1/pcr/m/n/10 sqlite3 \OT1/ptm/m/n/10 mod-ule has two d e-fault adapters for Python's built-in \OT1/pcr/m/n/10 datetime.date \OT1/ptm/m /n/10 and No file sqlite3/adapter_datetime.py. LaTeX Warning: Reference `sqlite3-Module-Contents' on page 392 undefined on inp ut line 563. No file sqlite3/converter_point.py. No file sqlite3/pysqlite_datetime.py. [392] No file sqlite3/shortcut_methods.py. ) (/home/neal/python/trunk/Doc/lib/liballos.tex [393] [394] Chapter 14. ) (/home/neal/python/trunk/Doc/lib/libos.tex [395] LaTeX Warning: Reference `os-file-dir' on page 396 undefined on input line 124. [396] [397] [398] LaTeX Warning: Reference `popen2-flow-control' on page 399 undefined on input l ine 409. [399] [400] [401] [402] [403] [404] [405] LaTeX Warning: Reference `os-newstreams' on page 406 undefined on input line 11 87. [406] LaTeX Warning: Reference `os-newstreams' on page 407 undefined on input line 11 99. [407] [408] [409] LaTeX Warning: Reference `os-newstreams' on page 410 undefined on input line 15 79. [410] [411] [412] [413] [414]) (/home/neal/python/trunk/Doc/lib/libtime.tex [415] [416] [417] [418] [419] LaTeX Warning: Reference `module-datetime' on page 420 undefined on input line 460. LaTeX Warning: Reference `module-locale' on page 420 undefined on input line 46 3. LaTeX Warning: Reference `module-calendar' on page 420 undefined on input line 466. ) (/home/neal/python/trunk/Doc/lib/liboptparse.tex [420] [421] [422] [423] LaTeX Warning: Reference `optparse-extending-optparse' on page 424 undefined on input line 311. [424] LaTeX Warning: Reference `optparse-extending-optparse' on page 425 undefined on input line 376. [425] LaTeX Warning: Reference `optparse-reference-guide' on page 426 undefined on in put line 413. LaTeX Warning: Reference `optparse-option-callbacks' on page 426 undefined on i nput line 413. [426] [427] Underfull \hbox (badness 5726) in paragraph at lines 516--519 []\OT1/pcr/m/n/10 optparse \OT1/ptm/m/n/10 ex-pands \OT1/pcr/m/n/10 "%prog" \OT 1/ptm/m/n/10 in the us-age string to the name of the cur-rent pro-gram, i.e. [428] [429] LaTeX Warning: Reference `optparse-conflicts-between-options' on page 430 undef ined on input line 704. [430] LaTeX Warning: Reference `optparse-tutorial' on page 431 undefined on input lin e 728. [431] [432] [433] [434] LaTeX Warning: Reference `optparse-option-callbacks' on page 435 undefined on i nput line 1008. [435] LaTeX Warning: Reference `optparse-option-callbacks' on page 436 undefined on i nput line 1121. LaTeX Warning: Reference `optparse-tutorial' on page 436 undefined on input lin e 1142. LaTeX Warning: Reference `optparse-extending-optparse' on page 436 undefined on input line 1151. [436] [437] [438] [439] [440] [441] [442] [443] [444] [445] [446]) (/home/neal/python/trunk/Doc/lib/libgetopt.tex [447] [448] LaTeX Warning: Reference `module-optparse' on page 449 undefined on input line 153. ) (/home/neal/python/trunk/Doc/lib/liblogging.tex [449] [450] Overfull \hbox (10.29729pt too wide) in paragraph at lines 213--213 []\OT1/pcr/m/n/9 2006-02-08 22:20:02,165 192.168.0.1 fbloggs Protocol problem: connection reset[] [451] [452] Overfull \hbox (240.35738pt too wide) in paragraph at lines 317--328 [] [453] Overfull \hbox (10.29729pt too wide) in paragraph at lines 441--441 []\OT1/pcr/m/n/9 2006-02-08 22:20:02,165 192.168.0.1 fbloggs Protocol problem: connection reset[] [454] [455] LaTeX Warning: Reference `typesseq-strings' on page 456 undefined on input line 599. Overfull \hbox (367.90819pt too wide) in paragraph at lines 603--614 [] [456] [457] [458] [459] Overfull \vbox (288.57pt too high) has occurred while \output is active [460] [461] [462] [463] [464] [465] [466] LaTeX Warning: Reference `typesseq-strings' on page 467 undefined on input line 1411. Overfull \hbox (403.90819pt too wide) in paragraph at lines 1416--1448 [] [467] [468] [469] [470] [471] [472]) (/home/neal/python/trunk/Doc/lib/libgetpass.tex) (/home/neal/python/trunk/Doc/lib/libcurses.tex LaTeX Warning: Reference `module-curses.ascii' on page 473 undefined on input l ine 26. LaTeX Warning: Reference `module-curses.panel' on page 473 undefined on input l ine 28. LaTeX Warning: Reference `module-curses.textpad' on page 473 undefined on input line 30. LaTeX Warning: Reference `module-curses.wrapper' on page 473 undefined on input line 33. [473] [474] [475] [476] [477] [478] [479] [480] [481] [482] [483] [484] [485] Package longtable Warning: Column widths have changed (longtable) in table 14.1 on input line 1169. [486] Package longtable Warning: Column widths have changed (longtable) in table 14.2 on input line 1241. [487] [488]) (/home/neal/python/trunk/Doc/lib/libascii.tex [489] [490] [491]) (/home/neal/python/trunk/Doc/lib/libcursespanel.tex [492]) (/home/neal/python/trunk/Doc/lib/libplatform.tex [493] [494]) (/home/neal/python/trunk/Doc/lib/liberrno.tex [495] [496] [497] [498] [499] [500]) (/home/neal/python/trunk/Doc/lib/libctypes.tex [501] [502] [503] Overfull \hbox (6.48393pt too wide) in paragraph at lines 227--390 [] [504] [505] Overfull \hbox (28.49721pt too wide) in paragraph at lines 459--459 []\OT1/pcr/m/n/9 >>> p = create_string_buffer(3) # create a 3 byte buffer, initialized to NUL bytes[] Overfull \hbox (71.69716pt too wide) in paragraph at lines 459--459 []\OT1/pcr/m/n/9 >>> p = create_string_buffer("Hello") # create a buffer c ontaining a NUL terminated string[] Overfull \hbox (23.09721pt too wide) in paragraph at lines 489--489 []\OT1/pcr/m/n/9 ArgumentError: argument 2: exceptions.TypeError: Don't know ho w to convert parameter 2[] [506] [507] [508] [509] [510] [511] [512] [513] [514] Overfull \hbox (12.29723pt too wide) in paragraph at lines 979--979 []\OT1/pcr/m/n/9 TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance[] [515] [516] [517] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] [518] [519] [520] [521] [522] [523] [524] [525] [526] [527] Overfull \hbox (89.29726pt too wide) in paragraph at lines 1827--1827 []\OT1/pcr/m/n/9 >>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "capti on", None), (1, "flags", 0)[] Overfull \hbox (13.69734pt too wide) in paragraph at lines 1856--1856 []\OT1/pcr/m/n/9 >>> GetWindowRect = prototype(("GetWindowRect", windll.user32) , paramflags)[] [528] [529] [530] [531] [532] [533] [534] LaTeX Warning: Reference `ctypes-pointers' on page 535 undefined on input line 2448. LaTeX Warning: Reference `ctypes-arrays' on page 535 undefined on input line 24 49. ) (/home/neal/python/trunk/Doc/lib/libsomeos.tex [535] [536] Chapter 15. ) (/home/neal/python/trunk/Doc/lib/libselect.tex LaTeX Warning: Reference `poll-objects' on page 537 undefined on input line 29. [537]) (/home/neal/python/trunk/Doc/lib/libthread.tex [538] [539]) (/home/neal/python/trunk/Doc/lib/libthreading.tex [540] [541] [542] [543] [544] [545] [546] [547]) (/home/neal/python/trunk/Doc/lib/libdummythread.tex) (/home/neal/python/trunk/Doc/lib/libdummythreading.tex [548]) (/home/neal/python/trunk/Doc/lib/libmmap.tex [549] ! Undefined control sequence. \\methoddesc ...fulllineitems} \ifx #1\@undefined \methodline {#2}{#3} \else... l.92 \begin{methoddesc}[mmap]{close}{} ? ! Emergency stop. \\methoddesc ...fulllineitems} \ifx #1\@undefined \methodline {#2}{#3} \else... l.92 \begin{methoddesc}[mmap]{close}{} Output written on lib.dvi (555 pages, 1939256 bytes). Transcript written on lib.log. *** Session transcript and error messages are in /home/neal/python/trunk/Doc/html/lib/lib.how. *** Exited with status 1. +++ TEXINPUTS=/home/neal/python/trunk/Doc/lib:/home/neal/python/trunk/Doc/commontex:/home/neal/python/trunk/Doc/paper-letter:/home/neal/python/trunk/Doc/texinputs: +++ latex lib make: *** [html/lib/lib.html] Error 1 From buildbot at python.org Mon Apr 2 12:41:31 2007 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Apr 2007 10:41:31 +0000 Subject: [Python-checkins] buildbot failure in x86 cygwin trunk Message-ID: <20070402104131.B6A521E400B@bag.python.org> The Buildbot has detected a new failure of x86 cygwin trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520cygwin%2520trunk/builds/20 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon,neal.norwitz BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Mon Apr 2 17:21:37 2007 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 2 Apr 2007 17:21:37 +0200 (CEST) Subject: [Python-checkins] r54656 - sandbox/trunk/abc/abc.py sandbox/trunk/abc/test_abc.py Message-ID: <20070402152137.6C6231E400A@bag.python.org> Author: guido.van.rossum Date: Mon Apr 2 17:21:36 2007 New Revision: 54656 Modified: sandbox/trunk/abc/abc.py sandbox/trunk/abc/test_abc.py Log: Experiment with adapters. Modified: sandbox/trunk/abc/abc.py ============================================================================== --- sandbox/trunk/abc/abc.py (original) +++ sandbox/trunk/abc/abc.py Mon Apr 2 17:21:36 2007 @@ -288,6 +288,9 @@ class _MappingView: + def __new__(cls, *args): + return object.__new__(cls) + def __init__(self, mapping): self._mapping = mapping @@ -544,3 +547,39 @@ if h == -1: h = -2 return h + + +### ADAPTERS ### + + +class AdaptToSequence(Sequence): + + def __new__(cls, *args): + return Sequence.__new__(cls) + + def __init__(self, adaptee): + self.adaptee = adaptee + + def __getitem__(self, index): + return self.adaptee[index] + + def __len__(self): + return len(self.adaptee) + + +class AdaptToMapping(SizeableMapping): + + def __new__(cls, *args): + return SizeableMapping.__new__(cls) + + def __init__(self, adaptee): + self.adaptee = adaptee + + def __getitem__(self, index): + return self.adaptee[index] + + def __len__(self): + return len(self.adaptee) + + def __iter__(self): + return iter(self.adaptee) Modified: sandbox/trunk/abc/test_abc.py ============================================================================== --- sandbox/trunk/abc/test_abc.py (original) +++ sandbox/trunk/abc/test_abc.py Mon Apr 2 17:21:36 2007 @@ -38,6 +38,33 @@ htl = hash(tuple(l)) self.assertEqual(hcl, htl, repr((l, hcl, htl))) + def test_adapt_to_sequence(self): + a = abc.AdaptToSequence(range(10)) + self.assertEqual(len(a), 10) + self.assertEqual(a[0], 0) + self.assertEqual(a[9], 9) + self.assertEqual(a[-1], 9) + self.assertEqual(list(a), range(10)) + #self.assertEqual(a, range(10)) + # Slicing isn't implemented correctly + + def test_adapt_to_mapping(self): + a = abc.AdaptToMapping({1: 10, 2: 20}) + self.assertEqual(len(a), 2) + self.assertEqual(a[1], 10) + self.assertEqual(a.get(2), 20) + self.assertEqual(a.get(3), None) + self.assertEqual(a.get(4, 42), 42) + self.assertEqual(1 in a, True) + self.assertEqual(2 in a, True) + self.assertEqual(3 in a, False) + self.assertEqual(set(a.keys()), {1, 2}) + self.assertEqual(set(a.items()), {(1, 10), (2, 20)}) + self.assertEqual(set(a.values()), {10, 20}) + #self.assertEqual(a.keys(), {1, 2}) + #self.assertEqual(a.items(), {(1, 10), (2, 20)}) + #self.assertEqual(a.values(), {10, 20}) + if __name__ == "__main__": unittest.main() From python-checkins at python.org Mon Apr 2 19:03:53 2007 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 2 Apr 2007 19:03:53 +0200 (CEST) Subject: [Python-checkins] r54657 - in python/branches/release25-maint: Lib/test/test_array.py Misc/NEWS Modules/arraymodule.c Message-ID: <20070402170353.44A4C1E400A@bag.python.org> Author: raymond.hettinger Date: Mon Apr 2 19:03:46 2007 New Revision: 54657 Modified: python/branches/release25-maint/Lib/test/test_array.py python/branches/release25-maint/Misc/NEWS python/branches/release25-maint/Modules/arraymodule.c Log: SF #1693079 Array module cannot pickle empty arrays Modified: python/branches/release25-maint/Lib/test/test_array.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_array.py (original) +++ python/branches/release25-maint/Lib/test/test_array.py Mon Apr 2 19:03:46 2007 @@ -111,6 +111,21 @@ self.assertEqual(a.x, b.x) self.assertEqual(type(a), type(b)) + def test_pickle_for_empty_array(self): + for protocol in (0, 1, 2): + a = array.array(self.typecode) + b = loads(dumps(a, protocol)) + self.assertNotEqual(id(a), id(b)) + self.assertEqual(a, b) + + a = ArraySubclass(self.typecode) + a.x = 10 + b = loads(dumps(a, protocol)) + self.assertNotEqual(id(a), id(b)) + self.assertEqual(a, b) + self.assertEqual(a.x, b.x) + self.assertEqual(type(a), type(b)) + def test_insert(self): a = array.array(self.typecode, self.example) a.insert(0, self.example[0]) Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Mon Apr 2 19:03:46 2007 @@ -134,6 +134,8 @@ Extension Modules ----------------- +- Bug #1693079: The array module can now successfully pickle empty arrays. + - Bug #1688393: Prevent crash in socket.recvfrom if length is negative. - Bug #1622896: fix a rare corner case where the bz2 module raised an Modified: python/branches/release25-maint/Modules/arraymodule.c ============================================================================== --- python/branches/release25-maint/Modules/arraymodule.c (original) +++ python/branches/release25-maint/Modules/arraymodule.c Mon Apr 2 19:03:46 2007 @@ -1147,12 +1147,19 @@ dict = Py_None; Py_INCREF(dict); } - result = Py_BuildValue("O(cs#)O", - array->ob_type, - array->ob_descr->typecode, - array->ob_item, - array->ob_size * array->ob_descr->itemsize, - dict); + if (array->ob_size > 0) { + result = Py_BuildValue("O(cs#)O", + array->ob_type, + array->ob_descr->typecode, + array->ob_item, + array->ob_size * array->ob_descr->itemsize, + dict); + } else { + result = Py_BuildValue("O(c)O", + array->ob_type, + array->ob_descr->typecode, + dict); + } Py_DECREF(dict); return result; } From python-checkins at python.org Mon Apr 2 19:29:30 2007 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 2 Apr 2007 19:29:30 +0200 (CEST) Subject: [Python-checkins] r54658 - in python/trunk: Lib/test/test_array.py Modules/arraymodule.c Message-ID: <20070402172930.EA8071E400B@bag.python.org> Author: raymond.hettinger Date: Mon Apr 2 19:29:30 2007 New Revision: 54658 Modified: python/trunk/Lib/test/test_array.py python/trunk/Modules/arraymodule.c Log: SF #1693079: Cannot save empty array in shelve Modified: python/trunk/Lib/test/test_array.py ============================================================================== --- python/trunk/Lib/test/test_array.py (original) +++ python/trunk/Lib/test/test_array.py Mon Apr 2 19:29:30 2007 @@ -111,6 +111,21 @@ self.assertEqual(a.x, b.x) self.assertEqual(type(a), type(b)) + def test_pickle_for_empty_array(self): + for protocol in (0, 1, 2): + a = array.array(self.typecode) + b = loads(dumps(a, protocol)) + self.assertNotEqual(id(a), id(b)) + self.assertEqual(a, b) + + a = ArraySubclass(self.typecode) + a.x = 10 + b = loads(dumps(a, protocol)) + self.assertNotEqual(id(a), id(b)) + self.assertEqual(a, b) + self.assertEqual(a.x, b.x) + self.assertEqual(type(a), type(b)) + def test_insert(self): a = array.array(self.typecode, self.example) a.insert(0, self.example[0]) Modified: python/trunk/Modules/arraymodule.c ============================================================================== --- python/trunk/Modules/arraymodule.c (original) +++ python/trunk/Modules/arraymodule.c Mon Apr 2 19:29:30 2007 @@ -1147,12 +1147,19 @@ dict = Py_None; Py_INCREF(dict); } - result = Py_BuildValue("O(cs#)O", - array->ob_type, - array->ob_descr->typecode, - array->ob_item, - array->ob_size * array->ob_descr->itemsize, - dict); + if (array->ob_size > 0) { + result = Py_BuildValue("O(cs#)O", + array->ob_type, + array->ob_descr->typecode, + array->ob_item, + array->ob_size * array->ob_descr->itemsize, + dict); + } else { + result = Py_BuildValue("O(c)O", + array->ob_type, + array->ob_descr->typecode, + dict); + } Py_DECREF(dict); return result; } From python-checkins at python.org Mon Apr 2 19:31:28 2007 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 2 Apr 2007 19:31:28 +0200 (CEST) Subject: [Python-checkins] r54659 - sandbox/trunk/abc/abc.py sandbox/trunk/abc/test_abc.py Message-ID: <20070402173128.F17D81E400A@bag.python.org> Author: guido.van.rossum Date: Mon Apr 2 19:31:27 2007 New Revision: 54659 Modified: sandbox/trunk/abc/abc.py sandbox/trunk/abc/test_abc.py Log: Add set adaptation. Modified: sandbox/trunk/abc/abc.py ============================================================================== --- sandbox/trunk/abc/abc.py (original) +++ sandbox/trunk/abc/abc.py Mon Apr 2 19:31:27 2007 @@ -554,11 +554,10 @@ class AdaptToSequence(Sequence): - def __new__(cls, *args): - return Sequence.__new__(cls) - - def __init__(self, adaptee): + def __new__(cls, adaptee): + self = Sequence.__new__(cls) self.adaptee = adaptee + return self def __getitem__(self, index): return self.adaptee[index] @@ -569,11 +568,10 @@ class AdaptToMapping(SizeableMapping): - def __new__(cls, *args): - return SizeableMapping.__new__(cls) - - def __init__(self, adaptee): + def __new__(cls, adaptee): + self = SizeableMapping.__new__(cls) self.adaptee = adaptee + return self def __getitem__(self, index): return self.adaptee[index] @@ -583,3 +581,20 @@ def __iter__(self): return iter(self.adaptee) + + +class AdaptToSet(SizeableSet): + + def __new__(cls, adaptee): + self = SizeableSet.__new__(cls) + self.adaptee = adaptee + return self + + def __contains__(self, elem): + return elem in self.adaptee + + def __iter__(self): + return iter(self.adaptee) + + def __len__(self): + return len(self.adaptee) Modified: sandbox/trunk/abc/test_abc.py ============================================================================== --- sandbox/trunk/abc/test_abc.py (original) +++ sandbox/trunk/abc/test_abc.py Mon Apr 2 19:31:27 2007 @@ -65,6 +65,13 @@ #self.assertEqual(a.items(), {(1, 10), (2, 20)}) #self.assertEqual(a.values(), {10, 20}) + def test_adapt_to_set(self): + a = abc.AdaptToSet({1, 2, 3}) + self.assertEqual(1 in a, True) + self.assertEqual(2 in a, True) + self.assertEqual(42 in a, False) + self.assertEqual(len(a), 3) + if __name__ == "__main__": unittest.main() From python-checkins at python.org Mon Apr 2 19:39:53 2007 From: python-checkins at python.org (andrew.kuchling) Date: Mon, 2 Apr 2007 19:39:53 +0200 (CEST) Subject: [Python-checkins] r54660 - python/branches/amk-mailbox/Lib/mailbox.py Message-ID: <20070402173953.6EDB61E400A@bag.python.org> Author: andrew.kuchling Date: Mon Apr 2 19:39:52 2007 New Revision: 54660 Modified: python/branches/amk-mailbox/Lib/mailbox.py Log: Simplify MH.remove(). Locking a file and then removing it seems to be dodgy practice, and I don't see what good it does to lock a file you're about to remove completely. Modified: python/branches/amk-mailbox/Lib/mailbox.py ============================================================================== --- python/branches/amk-mailbox/Lib/mailbox.py (original) +++ python/branches/amk-mailbox/Lib/mailbox.py Mon Apr 2 19:39:52 2007 @@ -871,24 +871,9 @@ def remove(self, key): """Remove the keyed message; raise KeyError if it doesn't exist.""" path = os.path.join(self._path, str(key)) - try: - f = open(path, 'rb+') - except IOError, e: - if e.errno == errno.ENOENT: - raise KeyError('No message with key: %s' % key) - else: - raise - try: - if self._locked: - _lock_file(f) - try: - f.close() - os.remove(os.path.join(self._path, str(key))) - finally: - if self._locked: - _unlock_file(f) - finally: - f.close() + if not os.path.exists(path): + raise KeyError('No message with key: %s' % key) + os.remove(path) def __setitem__(self, key, message): """Replace the keyed message; raise KeyError if it doesn't exist.""" From python-checkins at python.org Mon Apr 2 20:08:48 2007 From: python-checkins at python.org (andrew.kuchling) Date: Mon, 2 Apr 2007 20:08:48 +0200 (CEST) Subject: [Python-checkins] r54661 - python/branches/amk-mailbox/Lib/test/test_mailbox.py Message-ID: <20070402180848.6E5931E400A@bag.python.org> Author: andrew.kuchling Date: Mon Apr 2 20:08:43 2007 New Revision: 54661 Modified: python/branches/amk-mailbox/Lib/test/test_mailbox.py Log: Add tests from David Watson that check that message keys don't change after various actions Modified: python/branches/amk-mailbox/Lib/test/test_mailbox.py ============================================================================== --- python/branches/amk-mailbox/Lib/test/test_mailbox.py (original) +++ python/branches/amk-mailbox/Lib/test/test_mailbox.py Mon Apr 2 20:08:43 2007 @@ -122,6 +122,38 @@ self.assert_(len(self._box) == 1) self.assertRaises(KeyError, lambda: self._box[key0]) + def test_double_shorten(self): + # Check that flush() can shorten the mailbox twice + self._test_remove_two_of_three(broken_locking=False) + + def test_remove_with_broken_locking(self): + # Check that a (broken) application releasing the lock and + # then removing messages using the existing keys does not + # delete the wrong messages. + self._test_remove_two_of_three(broken_locking=True) + + def _test_remove_two_of_three(self, broken_locking=False): + self._box.lock() + key0 = self._box.add(self._template % 0) + key1 = self._box.add(self._template % 1) + key2 = self._box.add(self._template % 2) + self._box.flush() + self._box.remove(key0) + self._box.flush() + if broken_locking: + # As the name suggests, code that does this is broken + # (releasing the lock invalidates the keys, in general), + # but ideally mailbox.py should not break it further. + self._box.unlock() + self._box.lock() + self._box.remove(key1) + self._box.flush() + self._box.unlock() + self._box.close() + self._box = self._factory(self._path) + self.assert_(len(self._box) == 1) + self.assert_(self._box.itervalues().next().get_payload() == '2') + def test_get(self): # Retrieve messages using get() key0 = self._box.add(self._template % 0) From nnorwitz at gmail.com Mon Apr 2 23:31:43 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Mon, 2 Apr 2007 17:31:43 -0400 Subject: [Python-checkins] Python Regression Test Failures doc (1) Message-ID: <20070402213143.GA21308@python.psfb.org> TEXINPUTS=/home/neal/python/trunk/Doc/commontex: python /home/neal/python/trunk/Doc/tools/mkhowto --html --about html/stdabout.dat --iconserver ../icons --favicon ../icons/pyfav.png --address "See About this document... for information on suggesting changes." --up-link ../index.html --up-title "Python Documentation Index" --global-module-index "../modindex.html" --dvips-safe --dir html/lib lib/lib.tex *** Session transcript and error messages are in /home/neal/python/trunk/Doc/html/lib/lib.how. *** Exited with status 1. The relevant lines from the transcript are: ------------------------------------------------------------------------ +++ latex lib This is TeX, Version 3.14159 (Web2C 7.4.5) (/home/neal/python/trunk/Doc/lib/lib.tex LaTeX2e <2001/06/01> Babel and hyphenation patterns for american, french, german, ngerman, n ohyphenation, loaded. (/home/neal/python/trunk/Doc/texinputs/manual.cls Document Class: manual 1998/03/03 Document class (Python manual) (/home/neal/python/trunk/Doc/texinputs/pypaper.sty (/usr/share/texmf/tex/latex/psnfss/times.sty) Using Times instead of Computer Modern. ) (/usr/share/texmf/tex/latex/misc/fancybox.sty Style option: `fancybox' v1.3 <2000/09/19> (tvz) ) (/usr/share/texmf/tex/latex/base/report.cls Document Class: report 2001/04/21 v1.4e Standard LaTeX document class (/usr/share/texmf/tex/latex/base/size10.clo)) (/home/neal/python/trunk/Doc/texinputs/fancyhdr.sty) Using fancier footers than usual. (/home/neal/python/trunk/Doc/texinputs/fncychap.sty) Using fancy chapter headings. (/home/neal/python/trunk/Doc/texinputs/python.sty (/usr/share/texmf/tex/latex/tools/longtable.sty) (/home/neal/python/trunk/Doc/texinputs/underscore.sty) (/usr/share/texmf/tex/latex/tools/verbatim.sty) (/usr/share/texmf/tex/latex/base/alltt.sty) (./lib.pla))) (/home/neal/python/trunk/Doc/commontex/boilerplate.tex (/home/neal/python/trunk/Doc/commontex/patchlevel.tex)) Writing index file lib.idx (./lib.aux LaTeX Warning: Label `dom-objects' multiply defined. ) (/usr/share/texmf/tex/latex/psnfss/ot1ptm.fd) (/usr/share/texmf/tex/latex/psnfss/ot1phv.fd) [1] (/home/neal/python/trunk/Doc/commontex/copyright.tex (/usr/share/texmf/tex/latex/psnfss/omsptm.fd)) [2] Adding blank page after the abstract. [1] [2] (./lib.toc) Adding blank page after the table of contents. [1] [2] (/home/neal/python/trunk/Doc/lib/libintro.tex Chapter 1. (/usr/share/texmf/tex/latex/psnfss/ot1pcr.fd)) (/home/neal/python/trunk/Doc/lib/libobjs.tex [1] [2] Chapter 2. ) (/home/neal/python/trunk/Doc/lib/libfuncs.tex [3] [4] [5] [6] [7] Underfull \hbox (badness 10000) in paragraph at lines 445--449 []\OT1/ptm/m/n/10 Note that \OT1/pcr/m/n/10 filter(function, \OT1/ptm/m/it/10 i t-er-able\OT1/pcr/m/n/10 ) \OT1/ptm/m/n/10 is equiv-a-lent to \OT1/pcr/m/n/10 [ item for item in \OT1/ptm/m/it/10 it-er-able \OT1/pcr/m/n/10 if [8] [9] [10] [11] [12] [13] [14] [15] [16] [17]) (/home/neal/python/trunk/Doc/lib/libexcs.tex Underfull \hbox (badness 10000) in paragraph at lines 78--82 \OT1/ptm/m/n/10 The base class for all built-in ex-cep-tions ex-cept \OT1/pcr/m /n/10 StopIteration\OT1/ptm/m/n/10 , \OT1/pcr/m/n/10 GeneratorExit\OT1/ptm/m/n/ 10 , [18] [19] [20] [21] No file ../../Lib/test/exception_hierarchy.txt. ) (/home/neal/python/trunk/Doc/lib/libconsts.tex) (/home/neal/python/trunk/Doc/lib/libstdtypes.tex [22] Chapter 3. [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] Overfull \hbox (8.48134pt too wide) in paragraph at lines 977--987 [] Overfull \hbox (141.78873pt too wide) in paragraph at lines 994--1019 [] [33] Overfull \hbox (44.61931pt too wide) in paragraph at lines 1103--1135 [] [34] [35] [36] Overfull \hbox (98.60141pt too wide) in paragraph at lines 1315--1343 [] Overfull \hbox (44.38484pt too wide) in paragraph at lines 1405--1461 [] [37] [38] LaTeX Warning: Reference `context-closing' on page 39 undefined on input line 1 583. [39] [40] [41] Underfull \hbox (badness 10000) in paragraph at lines 1836--1843 []\OT1/ptm/m/n/10 An ex-am-ple of a con-text man-ager that re-turns a re-lated ob-ject is the one re-turned by [42] [43] [44]) (/home/neal/python/trunk/Doc/lib/libstrings.tex [45] [46] Chapter 4. (./lib4.syn) Overfull \hbox (5.23152pt too wide) in paragraph at lines 7--8 [][] Underfull \hbox (badness 10000) in paragraph at lines 7--8 ) (/home/neal/python/trunk/Doc/lib/libstring.tex [47] [48] [49] [50] [51]) (/home/neal/python/trunk/Doc/lib/libre.tex [52] [53] [54] [55] [56] [57] [58] [59] [60] [61]) (/home/neal/python/trunk/Doc/lib/libstruct.tex [62] [63] [64]) (/home/neal/python/trunk/Doc/lib/libdifflib.tex [65] [66] [67] [68] [69] [70] [71] [72]) (/home/neal/python/trunk/Doc/lib/libstringio.tex [73] [74]) (/home/neal/python/trunk/Doc/lib/libtextwrap.tex [75] [76]) (/home/neal/python/trunk/Doc/lib/libcodecs.tex [77] Underfull \hbox (badness 5161) in paragraph at lines 52--56 []\OT1/ptm/m/n/10 The fac-tory func-tions must re-turn ob-jects pro-vid-ing the in-ter-faces de-fined by the base classes [78] [79] Overfull \hbox (405.07822pt too wide) in paragraph at lines 288--300 [] [80] [81] [82] [83] [84] [85] [86] Overfull \hbox (254.7505pt too wide) in alignment at lines 820--820 [] [] [] Overfull \hbox (254.7505pt too wide) in alignment at lines 820--901 [] [] [] Overfull \hbox (254.7505pt too wide) in alignment at lines 901--981 [] [] [] Overfull \hbox (254.7505pt too wide) in alignment at lines 981--1062 [] [] [] Overfull \hbox (254.7505pt too wide) in alignment at lines 1062--1142 [] [] [] [87] Overfull \hbox (254.7505pt too wide) in alignment at lines 1142--1167 [] [] [] Overfull \hbox (465.03658pt too wide) in paragraph at lines 1179--1268 [] [88] [89]) (/home/neal/python/trunk/Doc/lib/libunicodedata.tex [90]) (/home/neal/python/trunk/Doc/lib/libstringprep.tex [91] [92]) (/home/neal/python/trunk/Doc/lib/libfpformat.tex) Underfull \hbox (badness 10000) in paragraph at lines 50--98 (/home/neal/python/trunk/Doc/lib/datatypes.tex [93] [94] Chapter 5. (./lib5.syn)) (/home/neal/python/trunk/Doc/lib/libdatetime.tex [95] [96] Underfull \hbox (badness 10000) in paragraph at lines 185--187 \OT1/ptm/m/n/10 The small-est pos-si-ble dif-fer-ence be-tween non-equal \OT1/p cr/m/n/10 timedelta \OT1/ptm/m/n/10 ob-jects, (/usr/share/texmf/tex/latex/psnfss/omlptm.fd) [97] Overfull \hbox (44.65097pt too wide) in paragraph at lines 204--235 [] [98] [99] Underfull \hbox (badness 10000) in paragraph at lines 430--439 \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .month, \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .da y, 0, 0, 0, \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .weekday(), \OT1/ptm/m/it/10 d\OT 1/pcr/m/n/10 .toordinal() - date(\OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .year, 1, Underfull \hbox (badness 10000) in paragraph at lines 464--467 []\OT1/ptm/m/n/10 The ISO cal-en-dar is a widely used vari-ant of the Gre-go-ri an cal-en-dar. See [100] Underfull \hbox (badness 10000) in paragraph at lines 547--551 \OT1/ptm/m/n/10 Return the cur-rent lo-cal date-time, with \OT1/pcr/m/n/10 tzin fo None\OT1/ptm/m/n/10 . This is equiv-a-lent to Underfull \hbox (badness 10000) in paragraph at lines 561--566 []\OT1/ptm/m/n/10 Else \OT1/ptm/m/it/10 tz \OT1/ptm/m/n/10 must be an in-stance of a class \OT1/pcr/m/n/10 tzinfo \OT1/ptm/m/n/10 sub-class, and the cur-rent date Underfull \hbox (badness 10000) in paragraph at lines 561--566 \OT1/ptm/m/n/10 and time are con-verted to \OT1/ptm/m/it/10 tz\OT1/ptm/m/n/10 ' s time zone. In this case the re-sult is equiv-a-lent to Underfull \hbox (badness 10000) in paragraph at lines 582--586 []\OT1/ptm/m/n/10 Else \OT1/ptm/m/it/10 tz \OT1/ptm/m/n/10 must be an in-stance of a class \OT1/pcr/m/n/10 tzinfo \OT1/ptm/m/n/10 sub-class, and the times- Underfull \hbox (badness 10000) in paragraph at lines 582--586 \OT1/ptm/m/n/10 tamp is con-verted to \OT1/ptm/m/it/10 tz\OT1/ptm/m/n/10 's tim e zone. In this case the re-sult is equiv-a-lent to [101] Underfull \hbox (badness 5519) in paragraph at lines 646--648 \OT1/ptm/m/n/10 The lat-est rep-re-sentable \OT1/pcr/m/n/10 datetime\OT1/ptm/m/ n/10 , \OT1/pcr/m/n/10 datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, [102] [103] Underfull \hbox (badness 10000) in paragraph at lines 874--888 \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .weekday(), \OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .toordinal() - date(\OT1/ptm/m/it/10 d\OT1/pcr/m/n/10 .year, 1, 1).toordinal() + 1, dst)) \OT1/ptm/m/n/10 The [104] Underfull \hbox (badness 10000) in paragraph at lines 923--925 \OT1/ptm/m/n/10 Return a 3-tuple, (ISO year, ISO week num-ber, ISO week-day). T he same as Underfull \hbox (badness 5064) in paragraph at lines 960--969 \OT1/ptm/m/n/10 Return a string rep-re-sent-ing the date and time, for ex-am-pl e \OT1/pcr/m/n/10 datetime(2002, 12, 4, 20, Underfull \hbox (badness 10000) in paragraph at lines 960--969 \OT1/pcr/m/n/10 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'\OT1/ptm/m/n/10 . \ OT1/pcr/m/n/10 d.ctime() \OT1/ptm/m/n/10 is equiv-a-lent to [105] [106] [107] [108] [109] [110] [111] [112]) (/home/neal/python/trunk/Doc/lib/libcalendar.tex [113] [114] [115]) (/home/neal/python/trunk/Doc/lib/libcollections.tex [116] [117] [118] [119] [120] Overfull \hbox (6.89723pt too wide) in paragraph at lines 343--343 []\OT1/pcr/m/n/9 >>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('r ed', 1), ('blue', 4)][] [121] Overfull \hbox (4.8973pt too wide) in paragraph at lines 376--376 []\OT1/pcr/m/n/9 >>> p = Point(11, y=22) # instantiate with positional or k eyword arguments[] Overfull \hbox (31.89726pt too wide) in paragraph at lines 389--389 []\OT1/pcr/m/n/9 EmployeeRecord = NamedTuple('EmployeeRecord', 'name age title department paygrade')[] ) (/home/neal/python/trunk/Doc/lib/libheapq.tex [122] [123] [124]) (/home/neal/python/trunk/Doc/lib/libbisect.tex) (/home/neal/python/trunk/Doc/lib/libarray.tex [125] [126] [127] [128]) (/home/neal/python/trunk/Doc/lib/libsets.tex [129] Overfull \hbox (98.60141pt too wide) in paragraph at lines 137--165 [] [130] [131]) (/home/neal/python/trunk/Doc/lib/libsched.tex [132]) (/home/neal/python/trunk/Doc/lib/libmutex.tex [133]) (/home/neal/python/trunk/Doc/lib/libqueue.tex [134]) (/home/neal/python/trunk/Doc/lib/libweakref.tex [135] [136] [137] [138]) (/home/neal/python/trunk/Doc/lib/libuserdict.tex [139] [140]) (/home/neal/python/trunk/Doc/lib/libtypes.tex [141] [142] Underfull \hbox (badness 10000) in paragraph at lines 200--205 \OT1/ptm/m/n/10 The type of ob-jects de-fined in ex-ten-sion mod-ules with \OT1 /pcr/m/n/10 PyMemberDef\OT1/ptm/m/n/10 , such as [143]) (/home/neal/python/trunk/Doc/lib/libnew.tex) (/home/neal/python/trunk/Doc/lib/libcopy.tex [144]) (/home/neal/python/trunk/Doc/lib/libpprint.tex [145] [146] [147]) (/home/neal/python/trunk/Doc/lib/librepr.tex [148]) Underfull \hbox (badness 10000) in paragraph at lines 120--121 (/home/neal/python/trunk/Doc/lib/numeric.tex [149] [150] Chapter 6. (./lib6.syn)) (/home/neal/python/trunk/Doc/lib/libmath.tex [151] [152]) (/home/neal/python/trunk/Doc/lib/libcmath.tex [153] [154]) (/home/neal/python/trunk/Doc/lib/libdecimal.tex [155] [156] [157] [158] Overfull \hbox (21.09727pt too wide) in paragraph at lines 305--305 [] \OT1/pcr/m/n/9 digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6 ' | '7' | '8' | '9'[] [159] [160] [161] [162] [163] [164] [165] [166] [167] Overfull \vbox (959.57pt too high) has occurred while \output is active [168] [169] [170]) (/home/neal/python/trunk/Doc/lib/librandom.tex [171] Underfull \hbox (badness 6575) in paragraph at lines 119--124 \OT1/ptm/m/n/10 Return a ran-domly se-lected el-e-ment from \OT1/pcr/m/n/10 ran ge(\OT1/ptm/m/it/10 start\OT1/pcr/m/n/10 , \OT1/ptm/m/it/10 stop\OT1/pcr/m/n/10 , \OT1/ptm/m/it/10 step\OT1/pcr/m/n/10 )\OT1/ptm/m/n/10 . This is equiv-a-lent to [172] [173]) (/home/neal/python/trunk/Doc/lib/libitertools.tex [174] [175] [176] [177] Overfull \hbox (15.69728pt too wide) in paragraph at lines 323--323 [] \OT1/pcr/m/n/9 yield counter() # yields the fillvalue, or raises IndexError[] [178] [179] [180] [181]) (/home/neal/python/trunk/Doc/lib/libfunctools.tex [182] Overfull \vbox (255.57pt too high) has occurred while \output is active [183] [184]) (/home/neal/python/trunk/Doc/lib/liboperator.tex [185] [186] [187] [188] [189] [190]) (/home/neal/python/trunk/Doc/lib/netdata.tex [191] [192] Chapter 7. (./lib7.syn)) (/home/neal/python/trunk/Doc/lib/email.tex [193] LaTeX Warning: Reference `module-smtplib' on page 194 undefined on input line 5 8. LaTeX Warning: Reference `module-nntplib' on page 194 undefined on input line 5 9. (/home/neal/python/trunk/Doc/lib/emailmessage.tex [194] [195] [196] [197] [198] [199]) (/home/neal/python/trunk/Doc/lib/emailparser.tex [200] [201]) (/home/neal/python/trunk/Doc/lib/emailgenerator.tex [202]) (/home/neal/python/trunk/Doc/lib/emailmimebase.tex [203] [204]) (/home/neal/python/trunk/Doc/lib/emailheaders.tex [205] [206]) (/home/neal/python/trunk/Doc/lib/emailcharsets.tex [207] [208] [209]) (/home/neal/python/trunk/Doc/lib/emailencoders.tex) (/home/neal/python/trunk/Doc/lib/emailexc.tex [210]) (/home/neal/python/trunk/Doc/lib/emailutil.tex [211] [212]) (/home/neal/python/trunk/Doc/lib/emailiter.tex [213]) [214] [215] [216] [217] [218] [219] [220]) (/home/neal/python/trunk/Doc/lib/libmailcap.tex [221]) (/home/neal/python/trunk/Doc/lib/libmailbox.tex [222] Underfull \hbox (badness 10000) in paragraph at lines 72--73 [223] [224] [225] [226] [227] [228] (/usr/share/texmf/tex/latex/psnfss/omspcr.fd) [229] [230] [231] [232] [233] [234] [235] [236] [237] [238] [239]) (/home/neal/python/trunk/Doc/lib/libmhlib.tex [240] [241] [242]) (/home/neal/python/trunk/Doc/lib/libmimetools.tex [243]) (/home/neal/python/trunk/Doc/lib/libmimetypes.tex [244] [245] [246]) (/home/neal/python/trunk/Doc/lib/libmimewriter.tex [247]) (/home/neal/python/trunk/Doc/lib/libmimify.tex [248]) (/home/neal/python/trunk/Doc/lib/libmultifile.tex [249]) (/home/neal/python/trunk/Doc/lib/librfc822.tex [250] [251] [252] [253] Underfull \hbox (badness 7379) in paragraph at lines 254--270 []\OT1/pcr/m/n/10 Message \OT1/ptm/m/n/10 in-stances also sup-port a lim-ited m ap-ping in-ter-face. In par-tic-u-lar: \OT1/ptm/m/it/10 m\OT1/pcr/m/n/10 [name] \OT1/ptm/m/n/10 is like [254]) (/home/neal/python/trunk/Doc/lib/libbase64.tex [255] [256]) (/home/neal/python/trunk/Doc/lib/libbinhex.tex) (/home/neal/python/trunk/Doc/lib/libbinascii.tex [257] [258]) (/home/neal/python/trunk/Doc/lib/libquopri.tex [259]) (/home/neal/python/trunk/Doc/lib/libuu.tex) (/home/neal/python/trunk/Doc/lib/markup.tex [260] Chapter 8. (./lib8.syn)) (/home/neal/python/trunk/Doc/lib/libhtmlparser.tex [261] [262]) (/home/neal/python/trunk/Doc/lib/libsgmllib.tex [263] [264] [265]) (/home/neal/python/trunk/Doc/lib/libhtmllib.tex [266] LaTeX Warning: Reference `module-formatter' on page 267 undefined on input line 81. Underfull \hbox (badness 7168) in paragraph at lines 158--165 \OT1/ptm/m/n/10 This mod-ule de-fines three dic-tio-nar-ies, \OT1/pcr/m/n/10 na me2codepoint\OT1/ptm/m/n/10 , \OT1/pcr/m/n/10 codepoint2name\OT1/ptm/m/n/10 , a nd \OT1/pcr/m/n/10 entitydefs\OT1/ptm/m/n/10 . [267]) (/home/neal/python/trunk/Doc/lib/libpyexpat.tex [268] Underfull \hbox (badness 10000) in paragraph at lines 160--167 \OT1/ptm/m/n/10 Calling this with a true value for \OT1/ptm/m/it/10 flag \OT1/p tm/m/n/10 (the de-fault) will cause Ex-pat to call the [269] [270] [271] [272] [273] [274] [275]) (/home/neal/python/trunk/Doc/lib/xmldom.tex [276] [277] [278] [279] [280] [281] [282] [283] [284] Underfull \hbox (badness 10000) in paragraph at lines 807--810 \OT1/ptm/m/n/10 Exception when a node does not ex-ist in the ref-er-enced con-t ext. For ex-am-ple, [285]) (/home/neal/python/trunk/Doc/lib/xmldomminidom.tex [286] [287] [288] [289] Underfull \hbox (badness 10000) in paragraph at lines 242--246 []\OT1/pcr/m/n/10 const \OT1/ptm/m/n/10 dec-la-ra-tions map to vari-ables in th eir re-spec-tive scope (e.g. [290]) (/home/neal/python/trunk/Doc/lib/xmldompulldom.tex) (/home/neal/python/trunk/Doc/lib/xmlsax.tex [291] [292]) (/home/neal/python/trunk/Doc/lib/xmlsaxhandler.tex [293] [294] [295] [296]) (/home/neal/python/trunk/Doc/lib/xmlsaxutils.tex [297]) (/home/neal/python/trunk/Doc/lib/xmlsaxreader.tex [298] [299] Underfull \hbox (badness 10000) in paragraph at lines 159--163 \OT1/ptm/m/n/10 Return the cur-rent set-ting for fea-ture \OT1/ptm/m/it/10 fea- ture-name\OT1/ptm/m/n/10 . If the fea-ture is not rec-og-nized, Underfull \hbox (badness 6188) in paragraph at lines 173--177 \OT1/ptm/m/n/10 Return the cur-rent set-ting for prop-erty \OT1/ptm/m/it/10 pro p-er-ty-name\OT1/ptm/m/n/10 . If the prop-erty is not rec-og-nized, a [300] [301]) (/home/neal/python/trunk/Doc/lib/libetree.tex [302] [303] [304] [305] [306]) (/home/neal/python/trunk/Doc/lib/fileformats.tex [307] [308] Chapter 9. (./lib9.syn)) (/home/neal/python/trunk/Doc/lib/libcsv.tex [309] [310] [311] [312] [313]) (/home/neal/python/trunk/Doc/lib/libcfgparser.tex [314] Overfull \vbox (35.57pt too high) has occurred while \output is active [315] Underfull \hbox (badness 10000) in paragraph at lines 22--23 [316] LaTeX Warning: Reference `module-shlex' on page 317 undefined on input line 150 . [317] [318]) (/home/neal/python/trunk/Doc/lib/librobotparser.tex Overfull \hbox (1.49724pt too wide) in paragraph at lines 66--66 []\OT1/pcr/m/n/9 >>> rp.can_fetch("*", "http://www.musi-cal.com/cgi-bin/search? city=San+Francisco")[] ) (/home/neal/python/trunk/Doc/lib/libnetrc.tex [319]) (/home/neal/python/trunk/Doc/lib/libxdrlib.tex [320] [321] [322]) Underfull \hbox (badness 10000) in paragraph at lines 244--183 (/home/neal/python/trunk/Doc/lib/libcrypto.tex [323] [324] Chapter 10. (./lib10.syn)) (/home/neal/python/trunk/Doc/lib/libhashlib.tex [325]) (/home/neal/python/trunk/Doc/lib/libhmac.tex [326]) (/home/neal/python/trunk/Doc/lib/libmd5.tex [327]) (/home/neal/python/trunk/Doc/lib/libsha.tex [328]) (/home/neal/python/trunk/Doc/lib/filesys.tex [329] [330] Chapter 11. (./lib11.syn)) (/home/neal/python/trunk/Doc/lib/libposixpath.tex [331] [332] (/usr/share/texmf/tex/latex/psnfss/omsphv.fd) [333]) (/home/neal/python/trunk/Doc/lib/libfileinput.tex [334] [335] Underfull \hbox (badness 10000) in paragraph at lines 185--187 []\OT1/ptm/m/n/10 Usage ex-am-ple: `\OT1/pcr/m/n/10 fi = fileinput.FileInput(op enhook=fileinput.hook_- ) (/home/neal/python/trunk/Doc/lib/libstat.tex [336]) (/home/neal/python/trunk/Doc/lib/libstatvfs.tex [337] [338]) (/home/neal/python/trunk/Doc/lib/libfilecmp.tex [339]) (/home/neal/python/trunk/Doc/lib/libtempfile.tex [340] [341]) (/home/neal/python/trunk/Doc/lib/libglob.tex [342]) (/home/neal/python/trunk/Doc/lib/libfnmatch.tex [343]) (/home/neal/python/trunk/Doc/lib/liblinecache.tex) (/home/neal/python/trunk/Doc/lib/libshutil.tex [344] [345]) (/home/neal/python/trunk/Doc/lib/libdircache.tex) Underfull \hbox (badness 10000) in paragraph at lines 37--206 [346] (/home/neal/python/trunk/Doc/lib/archiving.tex [347] [348] Chapter 12. (./lib12.syn)) (/home/neal/python/trunk/Doc/lib/libzlib.tex [349] [350]) (/home/neal/python/trunk/Doc/lib/libgzip.tex [351]) (/home/neal/python/trunk/Doc/lib/libbz2.tex Underfull \hbox (badness 5460) in paragraph at lines 19--22 []\OT1/pcr/m/n/10 BZ2File \OT1/ptm/m/n/10 class im-ple-ments a com-plete file i n-ter-face, in-clud-ing \OT1/pcr/m/n/10 readline()\OT1/ptm/m/n/10 , \OT1/pcr/m/ n/10 readlines()\OT1/ptm/m/n/10 , [352] [353]) (/home/neal/python/trunk/Doc/lib/libzipfile.tex [354] [355] [356] [357]) (/home/neal/python/trunk/Doc/lib/libtarfile.tex [358] [359] Underfull \hbox (badness 5878) in paragraph at lines 234--241 []\OT1/ptm/m/n/10 The \OT1/ptm/m/it/10 en-cod-ing \OT1/ptm/m/n/10 ar-gu-ment de -fines the lo-cal char-ac-ter en-cod-ing. It de-faults to the value from [360] [361] [362] [363]) Underfull \hbox (badness 10000) in paragraph at lines 549--214 (/home/neal/python/trunk/Doc/lib/persistence.tex [364] Chapter 13. (./lib13.syn)) (/home/neal/python/trunk/Doc/lib/libpickle.tex [365] Underfull \hbox (badness 10000) in paragraph at lines 94--95 [366] [367] [368] [369] Underfull \hbox (badness 10000) in paragraph at lines 495--496 [370] [371] [372] [373] [374] [375]) (/home/neal/python/trunk/Doc/lib/libcopyreg.tex [376]) (/home/neal/python/trunk/Doc/lib/libshelve.tex [377] [378]) (/home/neal/python/trunk/Doc/lib/libmarshal.tex [379] Underfull \hbox (badness 10000) in paragraph at lines 38--39 [380]) (/home/neal/python/trunk/Doc/lib/libanydbm.tex [381]) (/home/neal/python/trunk/Doc/lib/libwhichdb.tex) (/home/neal/python/trunk/Doc/lib/libdbm.tex [382]) (/home/neal/python/trunk/Doc/lib/libgdbm.tex [383]) (/home/neal/python/trunk/Doc/lib/libdbhash.tex [384]) (/home/neal/python/trunk/Doc/lib/libbsddb.tex [385] [386]) (/home/neal/python/trunk/Doc/lib/libdumbdbm.tex [387] [388]) (/home/neal/python/trunk/Doc/lib/libsqlite3.tex [389] [390] [391] No file sqlite3/complete_statement.py. [392] No file sqlite3/collation_reverse.py. [393] No file sqlite3/row_factory.py. No file sqlite3/text_factory.py. No file sqlite3/execute_1.py. No file sqlite3/execute_2.py. [394] No file sqlite3/executemany_1.py. No file sqlite3/executemany_2.py. [395] No file sqlite3/adapter_point_1.py. [396] No file sqlite3/adapter_point_2.py. Underfull \hbox (badness 10000) in paragraph at lines 518--522 []\OT1/ptm/m/n/10 The \OT1/pcr/m/n/10 sqlite3 \OT1/ptm/m/n/10 mod-ule has two d e-fault adapters for Python's built-in \OT1/pcr/m/n/10 datetime.date \OT1/ptm/m /n/10 and No file sqlite3/adapter_datetime.py. No file sqlite3/converter_point.py. No file sqlite3/pysqlite_datetime.py. [397] No file sqlite3/shortcut_methods.py. ) (/home/neal/python/trunk/Doc/lib/liballos.tex [398] [399] [400] Chapter 14. (./lib14.syn)) (/home/neal/python/trunk/Doc/lib/libos.tex [401] [402] [403] [404] LaTeX Warning: Reference `popen2-flow-control' on page 405 undefined on input l ine 409. [405] [406] [407] [408] [409] [410] [411] [412] [413] [414] [415] [416] [417] [418] [419] [420]) (/home/neal/python/trunk/Doc/lib/libtime.tex [421] [422] [423] [424] [425] LaTeX Warning: Reference `module-locale' on page 426 undefined on input line 46 3. ) (/home/neal/python/trunk/Doc/lib/liboptparse.tex [426] [427] [428] [429] [430] [431] [432] [433] Underfull \hbox (badness 5726) in paragraph at lines 516--519 []\OT1/pcr/m/n/10 optparse \OT1/ptm/m/n/10 ex-pands \OT1/pcr/m/n/10 "%prog" \OT 1/ptm/m/n/10 in the us-age string to the name of the cur-rent pro-gram, i.e. [434] [435] [436] [437] [438] [439] [440] [441] [442] [443] [444] [445] [446] [447] [448] [449] [450] [451] [452]) (/home/neal/python/trunk/Doc/lib/libgetopt.tex [453] [454]) (/home/neal/python/trunk/Doc/lib/liblogging.tex [455] [456] Overfull \hbox (10.29729pt too wide) in paragraph at lines 213--213 []\OT1/pcr/m/n/9 2006-02-08 22:20:02,165 192.168.0.1 fbloggs Protocol problem: connection reset[] [457] [458] Overfull \hbox (240.35738pt too wide) in paragraph at lines 317--328 [] [459] Overfull \hbox (10.29729pt too wide) in paragraph at lines 441--441 []\OT1/pcr/m/n/9 2006-02-08 22:20:02,165 192.168.0.1 fbloggs Protocol problem: connection reset[] [460] [461] Overfull \hbox (367.90819pt too wide) in paragraph at lines 603--614 [] [462] [463] [464] [465] Overfull \vbox (288.57pt too high) has occurred while \output is active [466] [467] [468] [469] [470] [471] [472] Overfull \hbox (403.90819pt too wide) in paragraph at lines 1416--1448 [] [473] [474] [475] [476] [477] [478]) (/home/neal/python/trunk/Doc/lib/libgetpass.tex) (/home/neal/python/trunk/Doc/lib/libcurses.tex [479] [480] [481] [482] [483] [484] [485] [486] [487] [488] [489] [490] [491] [492] [493] [494]) (/home/neal/python/trunk/Doc/lib/libascii.tex [495] [496] [497]) (/home/neal/python/trunk/Doc/lib/libcursespanel.tex [498]) (/home/neal/python/trunk/Doc/lib/libplatform.tex [499] [500]) (/home/neal/python/trunk/Doc/lib/liberrno.tex [501] [502] [503] [504] [505] [506]) (/home/neal/python/trunk/Doc/lib/libctypes.tex [507] [508] [509] Overfull \hbox (6.48393pt too wide) in paragraph at lines 227--390 [] [510] [511] Overfull \hbox (28.49721pt too wide) in paragraph at lines 459--459 []\OT1/pcr/m/n/9 >>> p = create_string_buffer(3) # create a 3 byte buffer, initialized to NUL bytes[] Overfull \hbox (71.69716pt too wide) in paragraph at lines 459--459 []\OT1/pcr/m/n/9 >>> p = create_string_buffer("Hello") # create a buffer c ontaining a NUL terminated string[] Overfull \hbox (23.09721pt too wide) in paragraph at lines 489--489 []\OT1/pcr/m/n/9 ArgumentError: argument 2: exceptions.TypeError: Don't know ho w to convert parameter 2[] [512] [513] [514] [515] [516] [517] [518] [519] [520] Overfull \hbox (12.29723pt too wide) in paragraph at lines 979--979 []\OT1/pcr/m/n/9 TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance[] [521] [522] [523] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] Overfull \hbox (17.69722pt too wide) in paragraph at lines 1142--1142 []\OT1/pcr/m/n/9 py_cmp_func [] [524] [525] [526] [527] [528] [529] [530] [531] [532] [533] Overfull \hbox (89.29726pt too wide) in paragraph at lines 1827--1827 []\OT1/pcr/m/n/9 >>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "capti on", None), (1, "flags", 0)[] Overfull \hbox (13.69734pt too wide) in paragraph at lines 1856--1856 []\OT1/pcr/m/n/9 >>> GetWindowRect = prototype(("GetWindowRect", windll.user32) , paramflags)[] [534] [535] [536] [537] [538] [539] [540]) (/home/neal/python/trunk/Doc/lib/libsomeos.tex [541] [542] Chapter 15. (./lib15.syn)) (/home/neal/python/trunk/Doc/lib/libselect.tex [543]) (/home/neal/python/trunk/Doc/lib/libthread.tex [544] [545]) (/home/neal/python/trunk/Doc/lib/libthreading.tex [546] [547] [548] [549] [550] [551] [552] [553]) (/home/neal/python/trunk/Doc/lib/libdummythread.tex) (/home/neal/python/trunk/Doc/lib/libdummythreading.tex [554]) (/home/neal/python/trunk/Doc/lib/libmmap.tex [555] ! Undefined control sequence. \\methoddesc ...fulllineitems} \ifx #1\@undefined \methodline {#2}{#3} \else... l.92 \begin{methoddesc}[mmap]{close}{} ? ! Emergency stop. \\methoddesc ...fulllineitems} \ifx #1\@undefined \methodline {#2}{#3} \else... l.92 \begin{methoddesc}[mmap]{close}{} Output written on lib.dvi (561 pages, 1949192 bytes). Transcript written on lib.log. *** Session transcript and error messages are in /home/neal/python/trunk/Doc/html/lib/lib.how. *** Exited with status 1. +++ TEXINPUTS=/home/neal/python/trunk/Doc/lib:/home/neal/python/trunk/Doc/commontex:/home/neal/python/trunk/Doc/paper-letter:/home/neal/python/trunk/Doc/texinputs: +++ latex lib make: *** [html/lib/lib.html] Error 1 From python-checkins at python.org Tue Apr 3 00:39:13 2007 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Apr 2007 00:39:13 +0200 (CEST) Subject: [Python-checkins] r54662 - in python/branches/release25-maint: Lib/test/test_re.py Misc/NEWS Modules/arraymodule.c Message-ID: <20070402223913.0C4511E400A@bag.python.org> Author: raymond.hettinger Date: Tue Apr 3 00:39:08 2007 New Revision: 54662 Modified: python/branches/release25-maint/Lib/test/test_re.py python/branches/release25-maint/Misc/NEWS python/branches/release25-maint/Modules/arraymodule.c Log: Array module's buffer interface can now handle empty arrays. Modified: python/branches/release25-maint/Lib/test/test_re.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_re.py (original) +++ python/branches/release25-maint/Lib/test/test_re.py Tue Apr 3 00:39:08 2007 @@ -604,6 +604,13 @@ self.assertEqual(iter.next().span(), (4, 4)) self.assertRaises(StopIteration, iter.next) + def test_empty_array(self): + # SF buf 1647541 + import array + for typecode in 'cbBuhHiIlLfd': + a = array.array(typecode) + self.assertEqual(re.compile("bla").match(a), None) + self.assertEqual(re.compile("").match(a).groups(), ()) def run_re_tests(): from test.re_tests import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Tue Apr 3 00:39:08 2007 @@ -134,6 +134,8 @@ Extension Modules ----------------- +- Bug #1647541: Array module's buffer interface can now handle empty arrays. + - Bug #1693079: The array module can now successfully pickle empty arrays. - Bug #1688393: Prevent crash in socket.recvfrom if length is negative. Modified: python/branches/release25-maint/Modules/arraymodule.c ============================================================================== --- python/branches/release25-maint/Modules/arraymodule.c (original) +++ python/branches/release25-maint/Modules/arraymodule.c Tue Apr 3 00:39:08 2007 @@ -1745,6 +1745,8 @@ (objobjargproc)array_ass_subscr }; +static const void *emptybuf = ""; + static Py_ssize_t array_buffer_getreadbuf(arrayobject *self, Py_ssize_t index, const void **ptr) { @@ -1754,6 +1756,8 @@ return -1; } *ptr = (void *)self->ob_item; + if (*ptr == NULL) + *ptr = emptybuf; return self->ob_size*self->ob_descr->itemsize; } @@ -1766,6 +1770,8 @@ return -1; } *ptr = (void *)self->ob_item; + if (*ptr == NULL) + *ptr = emptybuf; return self->ob_size*self->ob_descr->itemsize; } From python-checkins at python.org Tue Apr 3 00:54:22 2007 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Apr 2007 00:54:22 +0200 (CEST) Subject: [Python-checkins] r54663 - in python/trunk: Lib/test/test_re.py Modules/arraymodule.c Message-ID: <20070402225422.F09781E400A@bag.python.org> Author: raymond.hettinger Date: Tue Apr 3 00:54:21 2007 New Revision: 54663 Modified: python/trunk/Lib/test/test_re.py python/trunk/Modules/arraymodule.c Log: Array module's buffer interface can now handle empty arrays. Modified: python/trunk/Lib/test/test_re.py ============================================================================== --- python/trunk/Lib/test/test_re.py (original) +++ python/trunk/Lib/test/test_re.py Tue Apr 3 00:54:21 2007 @@ -601,6 +601,13 @@ self.assertEqual(iter.next().span(), (4, 4)) self.assertRaises(StopIteration, iter.next) + def test_empty_array(self): + # SF buf 1647541 + import array + for typecode in 'cbBuhHiIlLfd': + a = array.array(typecode) + self.assertEqual(re.compile("bla").match(a), None) + self.assertEqual(re.compile("").match(a).groups(), ()) def run_re_tests(): from test.re_tests import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR Modified: python/trunk/Modules/arraymodule.c ============================================================================== --- python/trunk/Modules/arraymodule.c (original) +++ python/trunk/Modules/arraymodule.c Tue Apr 3 00:54:21 2007 @@ -1745,6 +1745,8 @@ (objobjargproc)array_ass_subscr }; +static const void *emptybuf = ""; + static Py_ssize_t array_buffer_getreadbuf(arrayobject *self, Py_ssize_t index, const void **ptr) { @@ -1754,6 +1756,8 @@ return -1; } *ptr = (void *)self->ob_item; + if (*ptr == NULL) + *ptr = emptybuf; return self->ob_size*self->ob_descr->itemsize; } @@ -1766,6 +1770,8 @@ return -1; } *ptr = (void *)self->ob_item; + if (*ptr == NULL) + *ptr = emptybuf; return self->ob_size*self->ob_descr->itemsize; } From python-checkins at python.org Tue Apr 3 01:55:42 2007 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 3 Apr 2007 01:55:42 +0200 (CEST) Subject: [Python-checkins] r54664 - in python/trunk/Lib: copy_reg.py test/test_array.py test/test_descr.py Message-ID: <20070402235542.959B71E400A@bag.python.org> Author: guido.van.rossum Date: Tue Apr 3 01:55:37 2007 New Revision: 54664 Modified: python/trunk/Lib/copy_reg.py python/trunk/Lib/test/test_array.py python/trunk/Lib/test/test_descr.py Log: Fix warnings about object.__init__() signature. Two (test_array and test_descr) were bug IMO; the third (copy_reg) is a work-around which recognizes that object.__init__() doesn't do anything. Modified: python/trunk/Lib/copy_reg.py ============================================================================== --- python/trunk/Lib/copy_reg.py (original) +++ python/trunk/Lib/copy_reg.py Tue Apr 3 01:55:37 2007 @@ -48,7 +48,8 @@ obj = object.__new__(cls) else: obj = base.__new__(cls, state) - base.__init__(obj, state) + if base.__init__ != object.__init__: + base.__init__(obj, state) return obj _HEAPTYPE = 1<<9 Modified: python/trunk/Lib/test/test_array.py ============================================================================== --- python/trunk/Lib/test/test_array.py (original) +++ python/trunk/Lib/test/test_array.py Tue Apr 3 01:55:37 2007 @@ -728,7 +728,6 @@ return array.array.__new__(cls, 'c', s) def __init__(self, s, color='blue'): - array.array.__init__(self, 'c', s) self.color = color def strip(self): Modified: python/trunk/Lib/test/test_descr.py ============================================================================== --- python/trunk/Lib/test/test_descr.py (original) +++ python/trunk/Lib/test/test_descr.py Tue Apr 3 01:55:37 2007 @@ -2305,7 +2305,6 @@ __slots__ = ['prec'] def __init__(self, value=0.0, prec=12): self.prec = int(prec) - float.__init__(self, value) def __repr__(self): return "%.*g" % (self.prec, self) vereq(repr(precfloat(1.1)), "1.1") From python-checkins at python.org Tue Apr 3 02:01:14 2007 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Apr 2007 02:01:14 +0200 (CEST) Subject: [Python-checkins] r54665 - python/branches/release25-maint/Lib/bisect.py Message-ID: <20070403000114.95E831E400A@bag.python.org> Author: raymond.hettinger Date: Tue Apr 3 02:01:09 2007 New Revision: 54665 Modified: python/branches/release25-maint/Lib/bisect.py Log: SF 1602378 Clarify docstrings for bisect Modified: python/branches/release25-maint/Lib/bisect.py ============================================================================== --- python/branches/release25-maint/Lib/bisect.py (original) +++ python/branches/release25-maint/Lib/bisect.py Tue Apr 3 02:01:09 2007 @@ -23,8 +23,8 @@ """Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e <= x, and all e in - a[i:] have e > x. So if x already appears in the list, i points just - beyond the rightmost x already there. + a[i:] have e > x. So if x already appears in the list, a.insert(x) will + insert just after the rightmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. @@ -62,8 +62,8 @@ """Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e < x, and all e in - a[i:] have e >= x. So if x already appears in the list, i points just - before the leftmost x already there. + a[i:] have e >= x. So if x already appears in the list, a.insert(x) will + insert just before the leftmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. From python-checkins at python.org Tue Apr 3 02:02:12 2007 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Apr 2007 02:02:12 +0200 (CEST) Subject: [Python-checkins] r54666 - python/trunk/Lib/bisect.py Message-ID: <20070403000212.E2B141E400A@bag.python.org> Author: raymond.hettinger Date: Tue Apr 3 02:02:11 2007 New Revision: 54666 Modified: python/trunk/Lib/bisect.py Log: SF 1602378 Clarify docstrings for bisect Modified: python/trunk/Lib/bisect.py ============================================================================== --- python/trunk/Lib/bisect.py (original) +++ python/trunk/Lib/bisect.py Tue Apr 3 02:02:11 2007 @@ -23,8 +23,8 @@ """Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e <= x, and all e in - a[i:] have e > x. So if x already appears in the list, i points just - beyond the rightmost x already there. + a[i:] have e > x. So if x already appears in the list, a.insert(x) will + insert just after the rightmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. @@ -62,8 +62,8 @@ """Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e < x, and all e in - a[i:] have e >= x. So if x already appears in the list, i points just - before the leftmost x already there. + a[i:] have e >= x. So if x already appears in the list, a.insert(x) will + insert just before the leftmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. From python-checkins at python.org Tue Apr 3 03:38:01 2007 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Apr 2007 03:38:01 +0200 (CEST) Subject: [Python-checkins] r54667 - python/branches/release25-maint/Doc/tut/tut.tex Message-ID: <20070403013801.A48161E400A@bag.python.org> Author: raymond.hettinger Date: Tue Apr 3 03:37:56 2007 New Revision: 54667 Modified: python/branches/release25-maint/Doc/tut/tut.tex Log: SF #1382213: Tutorial section 9.5.1 ignores MRO for new-style classes Modified: python/branches/release25-maint/Doc/tut/tut.tex ============================================================================== --- python/branches/release25-maint/Doc/tut/tut.tex (original) +++ python/branches/release25-maint/Doc/tut/tut.tex Tue Apr 3 03:37:56 2007 @@ -4329,8 +4329,7 @@ \end{verbatim} -The only rule necessary to explain the semantics is the resolution -rule used for class attribute references. This is depth-first, +For old-style classes, the only rule is depth-first, left-to-right. Thus, if an attribute is not found in \class{DerivedClassName}, it is searched in \class{Base1}, then (recursively) in the base classes of \class{Base1}, and only if it is @@ -4345,16 +4344,26 @@ rule makes no differences between direct and inherited attributes of \class{Base1}.) -It is clear that indiscriminate use of multiple inheritance is a -maintenance nightmare, given the reliance in Python on conventions to -avoid accidental name conflicts. A well-known problem with multiple -inheritance is a class derived from two classes that happen to have a -common base class. While it is easy enough to figure out what happens -in this case (the instance will have a single copy of ``instance -variables'' or data attributes used by the common base class), it is -not clear that these semantics are in any way useful. +For new-style classes, the method resolution order changes dynamically +to support cooperative calls to \function{super()}. This approach +is known in some other multiple-inheritance languages as call-next-method +and is more powerful than the super call found in single-inheritance languages. + +With new-style classes, dynamic ordering is necessary because all +cases of multiple inheritance exhibit one or more diamond relationships +(where one at least one of the parent classes can be accessed through +multiple paths from the bottommost class). For example, all new-style +classes inherit from \class{object}, so any case of multiple inheritance +provides more than one path to reach \class{object}. To keep the +base classes from being accessed more than once, the dynamic algorithm +linearizes the search order in a way that preserves the left-to-right +ordering specified in each class, that calls each parent only once, and +that is monotonic (meaning that a class can be subclassed without affecting +the precedence order of its parents). Taken together, these properties +make it possible to design reliable and extensible classes with +multiple inheritance. For more detail, see +\url{http://www.python.org/download/releases/2.3/mro/}. -%% XXX Add rules for new-style MRO? \section{Private Variables \label{private}} From python-checkins at python.org Tue Apr 3 03:39:45 2007 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Apr 2007 03:39:45 +0200 (CEST) Subject: [Python-checkins] r54668 - python/trunk/Doc/tut/tut.tex Message-ID: <20070403013945.BCE7C1E400A@bag.python.org> Author: raymond.hettinger Date: Tue Apr 3 03:39:43 2007 New Revision: 54668 Modified: python/trunk/Doc/tut/tut.tex Log: SF #1382213: Tutorial section 9.5.1 ignores MRO for new-style classes Modified: python/trunk/Doc/tut/tut.tex ============================================================================== --- python/trunk/Doc/tut/tut.tex (original) +++ python/trunk/Doc/tut/tut.tex Tue Apr 3 03:39:43 2007 @@ -4329,8 +4329,7 @@ \end{verbatim} -The only rule necessary to explain the semantics is the resolution -rule used for class attribute references. This is depth-first, +For old-style classes, the only rule is depth-first, left-to-right. Thus, if an attribute is not found in \class{DerivedClassName}, it is searched in \class{Base1}, then (recursively) in the base classes of \class{Base1}, and only if it is @@ -4345,16 +4344,26 @@ rule makes no differences between direct and inherited attributes of \class{Base1}.) -It is clear that indiscriminate use of multiple inheritance is a -maintenance nightmare, given the reliance in Python on conventions to -avoid accidental name conflicts. A well-known problem with multiple -inheritance is a class derived from two classes that happen to have a -common base class. While it is easy enough to figure out what happens -in this case (the instance will have a single copy of ``instance -variables'' or data attributes used by the common base class), it is -not clear that these semantics are in any way useful. +For new-style classes, the method resolution order changes dynamically +to support cooperative calls to \function{super()}. This approach +is known in some other multiple-inheritance languages as call-next-method +and is more powerful than the super call found in single-inheritance languages. + +With new-style classes, dynamic ordering is necessary because all +cases of multiple inheritance exhibit one or more diamond relationships +(where one at least one of the parent classes can be accessed through +multiple paths from the bottommost class). For example, all new-style +classes inherit from \class{object}, so any case of multiple inheritance +provides more than one path to reach \class{object}. To keep the +base classes from being accessed more than once, the dynamic algorithm +linearizes the search order in a way that preserves the left-to-right +ordering specified in each class, that calls each parent only once, and +that is monotonic (meaning that a class can be subclassed without affecting +the precedence order of its parents). Taken together, these properties +make it possible to design reliable and extensible classes with +multiple inheritance. For more detail, see +\url{http://www.python.org/download/releases/2.3/mro/}. -%% XXX Add rules for new-style MRO? \section{Private Variables \label{private}} From python-checkins at python.org Tue Apr 3 06:36:07 2007 From: python-checkins at python.org (matthias.klose) Date: Tue, 3 Apr 2007 06:36:07 +0200 (CEST) Subject: [Python-checkins] r54669 - in python/trunk: Misc/NEWS Modules/_localemodule.c Message-ID: <20070403043607.95EED1E4014@bag.python.org> Author: matthias.klose Date: Tue Apr 3 06:35:59 2007 New Revision: 54669 Modified: python/trunk/Misc/NEWS python/trunk/Modules/_localemodule.c Log: - Fix an off-by-one bug in locale.strxfrm(). patch taken from http://bugs.debian.org/416934. Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Apr 3 06:35:59 2007 @@ -681,6 +681,9 @@ - Bug #1633621: if curses.resizeterm() or curses.resize_term() is called, update _curses.LINES, _curses.COLS, curses.LINES and curses.COLS. +- Fix an off-by-one bug in locale.strxfrm(). + + Tests ----- Modified: python/trunk/Modules/_localemodule.c ============================================================================== --- python/trunk/Modules/_localemodule.c (original) +++ python/trunk/Modules/_localemodule.c Tue Apr 3 06:35:59 2007 @@ -360,7 +360,7 @@ buf = PyMem_Malloc(n1); if (!buf) return PyErr_NoMemory(); - n2 = strxfrm(buf, s, n1); + n2 = strxfrm(buf, s, n1) + 1; if (n2 > n1) { /* more space needed */ buf = PyMem_Realloc(buf, n2); From python-checkins at python.org Tue Apr 3 06:39:36 2007 From: python-checkins at python.org (matthias.klose) Date: Tue, 3 Apr 2007 06:39:36 +0200 (CEST) Subject: [Python-checkins] r54670 - in python/branches/release25-maint: Misc/NEWS Modules/_localemodule.c Message-ID: <20070403043936.E0E2F1E400A@bag.python.org> Author: matthias.klose Date: Tue Apr 3 06:39:34 2007 New Revision: 54670 Modified: python/branches/release25-maint/Misc/NEWS python/branches/release25-maint/Modules/_localemodule.c Log: - Fix an off-by-one bug in locale.strxfrm(). Patch taken from http://bugs.debian.org/416934. Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Tue Apr 3 06:39:34 2007 @@ -220,6 +220,8 @@ - Bug #1633621: if curses.resizeterm() or curses.resize_term() is called, update _curses.LINES, _curses.COLS, curses.LINES and curses.COLS. +- Fix an off-by-one bug in locale.strxfrm(). + Library ------- Modified: python/branches/release25-maint/Modules/_localemodule.c ============================================================================== --- python/branches/release25-maint/Modules/_localemodule.c (original) +++ python/branches/release25-maint/Modules/_localemodule.c Tue Apr 3 06:39:34 2007 @@ -360,7 +360,7 @@ buf = PyMem_Malloc(n1); if (!buf) return PyErr_NoMemory(); - n2 = strxfrm(buf, s, n1); + n2 = strxfrm(buf, s, n1) + 1; if (n2 > n1) { /* more space needed */ buf = PyMem_Realloc(buf, n2); From python-checkins at python.org Tue Apr 3 09:04:30 2007 From: python-checkins at python.org (georg.brandl) Date: Tue, 3 Apr 2007 09:04:30 +0200 (CEST) Subject: [Python-checkins] r54671 - python/trunk/Doc/texinputs/python.sty Message-ID: <20070403070430.EDC991E400A@bag.python.org> Author: georg.brandl Date: Tue Apr 3 09:04:27 2007 New Revision: 54671 Modified: python/trunk/Doc/texinputs/python.sty Log: Fix the strange case of \begin{methoddesc}[NNTP]{...} where \ifx#1\@undefined ended up comparing N and N, therefore executing the true part of the conditional, blowing up at \@undefined. Modified: python/trunk/Doc/texinputs/python.sty ============================================================================== --- python/trunk/Doc/texinputs/python.sty (original) +++ python/trunk/Doc/texinputs/python.sty Tue Apr 3 09:04:27 2007 @@ -612,7 +612,7 @@ \newenvironment{cfuncdesc}[4][\py at badkey]{ \begin{fulllineitems} \cfuncline{#2}{#3}{#4} - \ifx#1\@undefined\else% + \ifx\@undefined#1\relax\else% \emph{Return value: \textbf{#1}.}\\ \fi }{\end{fulllineitems}} @@ -629,7 +629,7 @@ \newenvironment{ctypedesc}[2][\py at badkey]{ \begin{fulllineitems} \item[\bfcode{#2}% - \ifx#1\@undefined% + \ifx\@undefined#1\relax% \index{#2@{\py at idxcode{#2}} (C type)} \else% \index{#2@{\py at idxcode{#1}} (C type)} @@ -712,7 +712,7 @@ % \begin{methoddesc}[classname]{methodname}{args} \newcommand{\methodline}[3][\@undefined]{ \methodlineni{#2}{#3} - \ifx#1\@undefined + \ifx\@undefined#1\relax \index{#2@{\py at idxcode{#2()}} (\py at thisclass\ method)} \else \index{#2@{\py at idxcode{#2()}} (#1 method)} @@ -720,7 +720,7 @@ } \newenvironment{methoddesc}[3][\@undefined]{ \begin{fulllineitems} - \ifx#1\@undefined + \ifx\@undefined#1\relax \methodline{#2}{#3} \else \def\py at thisclass{#1} @@ -740,7 +740,7 @@ % object data attribute -------------------------------------------------- % \begin{memberdesc}[classname]{membername} \newcommand{\memberline}[2][\py at classbadkey]{% - \ifx#1\@undefined + \ifx\@undefined#1\relax \memberlineni{#2} \index{#2@{\py at idxcode{#2}} (\py at thisclass\ attribute)} \else @@ -750,7 +750,7 @@ } \newenvironment{memberdesc}[2][\py at classbadkey]{ \begin{fulllineitems} - \ifx#1\@undefined + \ifx\@undefined#1\relax \memberline{#2} \else \def\py at thisclass{#1} @@ -1046,14 +1046,14 @@ % \versionchanged[short explanation]{2.0} % \newcommand{\versionadded}[2][\py at badkey]{% - \ifx#1\@undefined% + \ifx\@undefined#1\relax% { New in version #2. }% \else% { New in version #2:\ #1. }% \fi% } \newcommand{\versionchanged}[2][\py at badkey]{% - \ifx#1\@undefined% + \ifx\@undefined#1\relax% { Changed in version #2. }% \else% { Changed in version #2:\ #1. }% From python-checkins at python.org Tue Apr 3 16:05:12 2007 From: python-checkins at python.org (facundo.batista) Date: Tue, 3 Apr 2007 16:05:12 +0200 (CEST) Subject: [Python-checkins] r54672 - in python/trunk: Doc/lib/libpoplib.tex Lib/test/test_socket_ssl.py Message-ID: <20070403140512.DFFDD1E401E@bag.python.org> Author: facundo.batista Date: Tue Apr 3 16:05:08 2007 New Revision: 54672 Modified: python/trunk/Doc/lib/libpoplib.tex python/trunk/Lib/test/test_socket_ssl.py Log: Now using unittest for the tests infraestructure. Also split the tests in those who need the network, and that who doesn't. Modified: python/trunk/Doc/lib/libpoplib.tex ============================================================================== --- python/trunk/Doc/lib/libpoplib.tex (original) +++ python/trunk/Doc/lib/libpoplib.tex Tue Apr 3 16:05:08 2007 @@ -50,8 +50,9 @@ One exception is defined as an attribute of the \module{poplib} module: \begin{excdesc}{error_proto} -Exception raised on any errors. The reason for the exception is -passed to the constructor as a string. +Exception raised on any errors from this module (errors from +\module{socket} module are not caught). The reason for the exception +is passed to the constructor as a string. \end{excdesc} \begin{seealso} Modified: python/trunk/Lib/test/test_socket_ssl.py ============================================================================== --- python/trunk/Lib/test/test_socket_ssl.py (original) +++ python/trunk/Lib/test/test_socket_ssl.py Tue Apr 3 16:05:08 2007 @@ -1,129 +1,133 @@ # Test just the SSL support in the socket module, in a moderately bogus way. import sys +import unittest from test import test_support import socket import errno - -# Optionally test SSL support. This requires the 'network' resource as given -# on the regrtest command line. -skip_expected = not (test_support.is_resource_enabled('network') and - hasattr(socket, "ssl")) - -def test_basic(): - test_support.requires('network') - - import urllib - - if test_support.verbose: - print "test_basic ..." - - socket.RAND_status() - try: - socket.RAND_egd(1) - except TypeError: - pass - else: - print "didn't raise TypeError" - socket.RAND_add("this is a random string", 75.0) - - with test_support.transient_internet(): - f = urllib.urlopen('https://sf.net') - buf = f.read() - f.close() - -def test_timeout(): - test_support.requires('network') - - def error_msg(extra_msg): - print >> sys.stderr, """\ - WARNING: an attempt to connect to %r %s, in - test_timeout. That may be legitimate, but is not the outcome we hoped - for. If this message is seen often, test_timeout should be changed to - use a more reliable address.""" % (ADDR, extra_msg) - - if test_support.verbose: - print "test_timeout ..." - - # A service which issues a welcome banner (without need to write - # anything). - # XXX ("gmail.org", 995) has been unreliable so far, from time to time - # XXX non-responsive for hours on end (& across all buildbot slaves, - # XXX so that's not just a local thing). - ADDR = "gmail.org", 995 - - s = socket.socket() - s.settimeout(30.0) - try: - s.connect(ADDR) - except socket.timeout: - error_msg('timed out') - return - except socket.error, exc: # In case connection is refused. - if exc.args[0] == errno.ECONNREFUSED: - error_msg('was refused') - return - else: - raise - - ss = socket.ssl(s) - # Read part of return welcome banner twice. - ss.read(1) - ss.read(1) - s.close() - -def test_rude_shutdown(): - if test_support.verbose: - print "test_rude_shutdown ..." - - try: - import threading - except ImportError: - return - - # Some random port to connect to. - PORT = [9934] - - listener_ready = threading.Event() - listener_gone = threading.Event() - - # `listener` runs in a thread. It opens a socket listening on PORT, and - # sits in an accept() until the main thread connects. Then it rudely - # closes the socket, and sets Event `listener_gone` to let the main thread - # know the socket is gone. - def listener(): - s = socket.socket() - PORT[0] = test_support.bind_port(s, '', PORT[0]) - s.listen(5) - listener_ready.set() - s.accept() - s = None # reclaim the socket object, which also closes it - listener_gone.set() - - def connector(): - listener_ready.wait() - s = socket.socket() - s.connect(('localhost', PORT[0])) - listener_gone.wait() +import threading +import subprocess +import time + +# Optionally test SSL support, if we have it in the tested platform +skip_expected = not hasattr(socket, "ssl") + +class ConnectedTests(unittest.TestCase): + + def testBasic(self): + import urllib + + if test_support.verbose: + print "test_basic ..." + + socket.RAND_status() try: - ssl_sock = socket.ssl(s) - except socket.sslerror: + socket.RAND_egd(1) + except TypeError: pass else: - raise test_support.TestFailed( + print "didn't raise TypeError" + socket.RAND_add("this is a random string", 75.0) + + with test_support.transient_internet(): + f = urllib.urlopen('https://sf.net') + buf = f.read() + f.close() + + def testTimeout(self): + def error_msg(extra_msg): + print >> sys.stderr, """\ + WARNING: an attempt to connect to %r %s, in + test_timeout. That may be legitimate, but is not the outcome we + hoped for. If this message is seen often, test_timeout should be + changed to use a more reliable address.""" % (ADDR, extra_msg) + + if test_support.verbose: + print "test_timeout ..." + + # A service which issues a welcome banner (without need to write + # anything). + # XXX ("gmail.org", 995) has been unreliable so far, from time to + # XXX time non-responsive for hours on end (& across all buildbot + # XXX slaves, so that's not just a local thing). + ADDR = "gmail.org", 995 + + s = socket.socket() + s.settimeout(30.0) + try: + s.connect(ADDR) + except socket.timeout: + error_msg('timed out') + return + except socket.error, exc: # In case connection is refused. + if exc.args[0] == errno.ECONNREFUSED: + error_msg('was refused') + return + else: + raise + + ss = socket.ssl(s) + # Read part of return welcome banner twice. + ss.read(1) + ss.read(1) + s.close() + +class BasicTests(unittest.TestCase): + + def testRudeShutdown(self): + if test_support.verbose: + print "test_rude_shutdown ..." + + # Some random port to connect to. + PORT = [9934] + + listener_ready = threading.Event() + listener_gone = threading.Event() + + # `listener` runs in a thread. It opens a socket listening on + # PORT, and sits in an accept() until the main thread connects. + # Then it rudely closes the socket, and sets Event `listener_gone` + # to let the main thread know the socket is gone. + def listener(): + s = socket.socket() + PORT[0] = test_support.bind_port(s, '', PORT[0]) + s.listen(5) + listener_ready.set() + s.accept() + s = None # reclaim the socket object, which also closes it + listener_gone.set() + + def connector(): + listener_ready.wait() + s = socket.socket() + s.connect(('localhost', PORT[0])) + listener_gone.wait() + try: + ssl_sock = socket.ssl(s) + except socket.sslerror: + pass + else: + raise test_support.TestFailed( 'connecting to closed SSL socket should have failed') + + t = threading.Thread(target=listener) + t.start() + connector() + t.join() - t = threading.Thread(target=listener) - t.start() - connector() - t.join() def test_main(): if not hasattr(socket, "ssl"): raise test_support.TestSkipped("socket module has no ssl support") - test_rude_shutdown() - test_basic() - test_timeout() + + tests = [BasicTests] + + if test_support.is_resource_enabled('network'): + tests.append(ConnectedTests) + + thread_info = test_support.threading_setup() + test_support.run_unittest(*tests) + test_support.threading_cleanup(*thread_info) if __name__ == "__main__": test_main() From fdrake at acm.org Tue Apr 3 16:09:49 2007 From: fdrake at acm.org (Fred L. Drake, Jr.) Date: Tue, 3 Apr 2007 10:09:49 -0400 Subject: [Python-checkins] r54671 - python/trunk/Doc/texinputs/python.sty In-Reply-To: <20070403070430.EDC991E400A@bag.python.org> References: <20070403070430.EDC991E400A@bag.python.org> Message-ID: <200704031009.49510.fdrake@acm.org> On Tuesday 03 April 2007 03:04, georg.brandl wrote: > Modified: > python/trunk/Doc/texinputs/python.sty > Log: > Fix the strange case of Yay Georg! This one had me stumped (and yes, I really was looking into it last night). Thanks! -Fred -- Fred L. Drake, Jr. From buildbot at python.org Tue Apr 3 16:10:21 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Apr 2007 14:10:21 +0000 Subject: [Python-checkins] buildbot failure in x86 OpenBSD trunk Message-ID: <20070403141022.54C381E400C@bag.python.org> The Buildbot has detected a new failure of x86 OpenBSD trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520OpenBSD%2520trunk/builds/1639 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: facundo.batista,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Tue Apr 3 16:47:04 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Apr 2007 14:47:04 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP trunk Message-ID: <20070403144705.299BB1E4011@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/353 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: facundo.batista,georg.brandl Build had warnings: warnings test Excerpt from the test logfile: 2 tests failed: test_os test_urllib ====================================================================== ERROR: test_makedir (test.test_os.MakedirTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_os.py", line 384, in setUp os.mkdir(test_support.TESTFN) WindowsError: [Error 183] Cannot create a file when that file already exists: '@test' ====================================================================== ERROR: test_access (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_os.py", line 451, in test_access self.assertRaises(WindowsError, os.utime, test_support.TESTFN, 0) File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\unittest.py", line 329, in failUnlessRaises callableObj(*args, **kwargs) TypeError: utime() arg 2 must be a tuple (atime, mtime) ====================================================================== FAIL: test_traversal (test.test_os.WalkTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_os.py", line 313, in test_traversal self.assertEqual(len(all), 4) AssertionError: 5 != 4 ====================================================================== FAIL: test_chdir (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_os.py", line 442, in test_chdir self.assertRaises(WindowsError, os.chdir, test_support.TESTFN) AssertionError: WindowsError not raised sincerely, -The Buildbot From python-checkins at python.org Tue Apr 3 18:08:14 2007 From: python-checkins at python.org (walter.doerwald) Date: Tue, 3 Apr 2007 18:08:14 +0200 (CEST) Subject: [Python-checkins] r54673 - python/trunk/Lib/test/test_structmembers.py python/trunk/Lib/test/test_warnings.py Message-ID: <20070403160814.BB70C1E4008@bag.python.org> Author: walter.doerwald Date: Tue Apr 3 18:08:10 2007 New Revision: 54673 Modified: python/trunk/Lib/test/test_structmembers.py python/trunk/Lib/test/test_warnings.py Log: Move the functionality for catching warnings in test_warnings.py into a separate class to that reusing the functionality in test_structmembers.py doesn't rerun the tests from test_warnings.py. Modified: python/trunk/Lib/test/test_structmembers.py ============================================================================== --- python/trunk/Lib/test/test_structmembers.py (original) +++ python/trunk/Lib/test/test_structmembers.py Tue Apr 3 18:08:10 2007 @@ -39,7 +39,7 @@ ts.T_ULONG=ULONG_MAX self.assertEquals(ts.T_ULONG, ULONG_MAX) -class TestWarnings(test.test_warnings.TestModule): +class TestWarnings(test.test_warnings.CatchWarningTest): def has_warned(self): self.assertEqual(test.test_warnings.msg.category, exceptions.RuntimeWarning.__name__) Modified: python/trunk/Lib/test/test_warnings.py ============================================================================== --- python/trunk/Lib/test/test_warnings.py (original) +++ python/trunk/Lib/test/test_warnings.py Tue Apr 3 18:08:10 2007 @@ -20,7 +20,7 @@ msg.filename = os.path.basename(filename) msg.lineno = lineno -class TestModule(unittest.TestCase): +class CatchWarningTest(unittest.TestCase): def setUp(self): global msg @@ -35,6 +35,8 @@ warnings.filters = self._filters[:] warnings.showwarning = self._showwarning +class TestModule(CatchWarningTest): + def test_warn_default_category(self): for i in range(4): text = 'multi %d' %i # Different text on each call From python-checkins at python.org Tue Apr 3 18:16:27 2007 From: python-checkins at python.org (walter.doerwald) Date: Tue, 3 Apr 2007 18:16:27 +0200 (CEST) Subject: [Python-checkins] r54674 - python/trunk/Lib/test/test_warnings.py Message-ID: <20070403161627.3AA961E4015@bag.python.org> Author: walter.doerwald Date: Tue Apr 3 18:16:24 2007 New Revision: 54674 Modified: python/trunk/Lib/test/test_warnings.py Log: Document that CatchWarningTests is reused by test_structmembers.py. Modified: python/trunk/Lib/test/test_warnings.py ============================================================================== --- python/trunk/Lib/test/test_warnings.py (original) +++ python/trunk/Lib/test/test_warnings.py Tue Apr 3 18:16:24 2007 @@ -21,6 +21,8 @@ msg.lineno = lineno class CatchWarningTest(unittest.TestCase): + # base class used for catching warnings issued by the + # warning framework (this is reused by test_structmembers.py) def setUp(self): global msg From buildbot at python.org Tue Apr 3 18:35:26 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Apr 2007 16:35:26 +0000 Subject: [Python-checkins] buildbot warnings in x86 W2k trunk Message-ID: <20070403163526.2F78E1E4012@bag.python.org> The Buildbot has detected a new failure of x86 W2k trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520W2k%2520trunk/builds/181 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: walter.doerwald Build had warnings: warnings test Excerpt from the test logfile: 3 tests failed: test_cProfile test_frozen test_os ====================================================================== ERROR: test_makedir (test.test_os.MakedirTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 384, in setUp os.mkdir(test_support.TESTFN) WindowsError: [Error 183] Cannot create a file when that file already exists: '@test' ====================================================================== ERROR: test_access (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 451, in test_access self.assertRaises(WindowsError, os.utime, test_support.TESTFN, 0) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\unittest.py", line 329, in failUnlessRaises callableObj(*args, **kwargs) TypeError: utime() arg 2 must be a tuple (atime, mtime) ====================================================================== FAIL: test_traversal (test.test_os.WalkTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 313, in test_traversal self.assertEqual(len(all), 4) AssertionError: 5 != 4 ====================================================================== FAIL: test_chdir (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 442, in test_chdir self.assertRaises(WindowsError, os.chdir, test_support.TESTFN) AssertionError: WindowsError not raised sincerely, -The Buildbot From collinw at gmail.com Tue Apr 3 18:47:34 2007 From: collinw at gmail.com (Collin Winter) Date: Tue, 3 Apr 2007 11:47:34 -0500 Subject: [Python-checkins] r54674 - python/trunk/Lib/test/test_warnings.py In-Reply-To: <20070403161627.3AA961E4015@bag.python.org> References: <20070403161627.3AA961E4015@bag.python.org> Message-ID: <43aa6ff70704030947y29f9d8diba694366e3d92355@mail.gmail.com> On 4/3/07, walter.doerwald wrote: > Author: walter.doerwald > Date: Tue Apr 3 18:16:24 2007 > New Revision: 54674 > > Modified: > python/trunk/Lib/test/test_warnings.py > Log: > Document that CatchWarningTests is reused by test_structmembers.py. Why not move this into test_support? Collin Winter From walter at livinglogic.de Tue Apr 3 18:48:25 2007 From: walter at livinglogic.de (=?ISO-8859-1?Q?Walter_D=F6rwald?=) Date: Tue, 03 Apr 2007 18:48:25 +0200 Subject: [Python-checkins] r54674 - python/trunk/Lib/test/test_warnings.py In-Reply-To: <43aa6ff70704030947y29f9d8diba694366e3d92355@mail.gmail.com> References: <20070403161627.3AA961E4015@bag.python.org> <43aa6ff70704030947y29f9d8diba694366e3d92355@mail.gmail.com> Message-ID: <46128559.1070608@livinglogic.de> Collin Winter wrote: > On 4/3/07, walter.doerwald wrote: >> Author: walter.doerwald >> Date: Tue Apr 3 18:16:24 2007 >> New Revision: 54674 >> >> Modified: >> python/trunk/Lib/test/test_warnings.py >> Log: >> Document that CatchWarningTests is reused by test_structmembers.py. > > Why not move this into test_support? Good idea! There might be other tests that could use this. I'm working on it. Servus, Walter From python-checkins at python.org Tue Apr 3 18:53:49 2007 From: python-checkins at python.org (walter.doerwald) Date: Tue, 3 Apr 2007 18:53:49 +0200 (CEST) Subject: [Python-checkins] r54675 - python/trunk/Lib/test/test_warnings.py python/trunk/Lib/test/warning_tests.py Message-ID: <20070403165349.BE9741E4008@bag.python.org> Author: walter.doerwald Date: Tue Apr 3 18:53:43 2007 New Revision: 54675 Added: python/trunk/Lib/test/warning_tests.py Modified: python/trunk/Lib/test/test_warnings.py Log: Add tests for the filename. Test that the stacklevel is handled correctly. Modified: python/trunk/Lib/test/test_warnings.py ============================================================================== --- python/trunk/Lib/test/test_warnings.py (original) +++ python/trunk/Lib/test/test_warnings.py Tue Apr 3 18:53:43 2007 @@ -3,6 +3,8 @@ import unittest from test import test_support +import warning_tests + # The warnings module isn't easily tested, because it relies on module # globals to store configuration information. setUp() and tearDown() # preserve the current settings to avoid bashing them while running tests. @@ -97,6 +99,28 @@ warnings._setoption('error::Warning::0') self.assertRaises(UserWarning, warnings.warn, 'convert to error') + def test_filename(self): + warning_tests.inner("spam1") + self.assertEqual(msg.filename, "warning_tests.py") + warning_tests.outer("spam2") + self.assertEqual(msg.filename, "warning_tests.py") + + def test_stacklevel(self): + # Test stacklevel argument + # make sure all messages are different, so the warning won't be skipped + warning_tests.inner("spam3", stacklevel=1) + self.assertEqual(msg.filename, "warning_tests.py") + warning_tests.outer("spam4", stacklevel=1) + self.assertEqual(msg.filename, "warning_tests.py") + + warning_tests.inner("spam5", stacklevel=2) + self.assertEqual(msg.filename, "test_warnings.py") + warning_tests.outer("spam6", stacklevel=2) + self.assertEqual(msg.filename, "warning_tests.py") + + warning_tests.inner("spam7", stacklevel=9999) + self.assertEqual(msg.filename, "sys") + def test_main(verbose=None): # Obscure hack so that this test passes after reloads or repeated calls Added: python/trunk/Lib/test/warning_tests.py ============================================================================== --- (empty file) +++ python/trunk/Lib/test/warning_tests.py Tue Apr 3 18:53:43 2007 @@ -0,0 +1,9 @@ +# Helper module for testing the skipmodules argument of warnings.warn() + +import warnings + +def outer(message, stacklevel=1): + inner(message, stacklevel) + +def inner(message, stacklevel=1): + warnings.warn(message, stacklevel=stacklevel) From buildbot at python.org Tue Apr 3 19:17:51 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Apr 2007 17:17:51 +0000 Subject: [Python-checkins] buildbot warnings in x86 mvlgcc trunk Message-ID: <20070403171751.D73FB1E4008@bag.python.org> The Buildbot has detected a new failure of x86 mvlgcc trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520mvlgcc%2520trunk/builds/436 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: walter.doerwald Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_socketserver Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 81, in run svr = svrcls(self.__addr, self.__hdlrcls) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 331, in __init__ self.server_bind() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 342, in server_bind self.socket.bind(self.server_address) File "", line 1, in bind error: (98, 'Address already in use') Traceback (most recent call last): File "./Lib/test/regrtest.py", line 557, in runtest_inner indirect_test() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 212, in test_main testall() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 195, in testall testloop(socket.AF_INET, tcpservers, MyStreamHandler, teststream) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 144, in testloop testfunc(proto, addr) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 64, in teststream buf = data = receive(s, 100) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 46, in receive return sock.recv(n) error: (104, 'Connection reset by peer') make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Apr 3 19:29:51 2007 From: python-checkins at python.org (facundo.batista) Date: Tue, 3 Apr 2007 19:29:51 +0200 (CEST) Subject: [Python-checkins] r54676 - python/trunk/Lib/test/ssl_cert.pem python/trunk/Lib/test/ssl_key.pem python/trunk/Lib/test/test_socket_ssl.py Message-ID: <20070403172951.014231E4011@bag.python.org> Author: facundo.batista Date: Tue Apr 3 19:29:48 2007 New Revision: 54676 Added: python/trunk/Lib/test/ssl_cert.pem python/trunk/Lib/test/ssl_key.pem Modified: python/trunk/Lib/test/test_socket_ssl.py Log: Added a SSL server to test_socket_ssl.py to be able to test locally. Now, it checks if have openssl available and run those specific tests (it starts openssl at the beggining of all the tests and then kills it at the end). Added: python/trunk/Lib/test/ssl_cert.pem ============================================================================== --- (empty file) +++ python/trunk/Lib/test/ssl_cert.pem Tue Apr 3 19:29:48 2007 @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICLDCCAdYCAQAwDQYJKoZIhvcNAQEEBQAwgaAxCzAJBgNVBAYTAlBUMRMwEQYD +VQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5ldXJv +bmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMTEmJy +dXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZpMB4X +DTk2MDkwNTAzNDI0M1oXDTk2MTAwNTAzNDI0M1owgaAxCzAJBgNVBAYTAlBUMRMw +EQYDVQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5l +dXJvbmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMT +EmJydXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZp +MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNw +L4lYKbpzzlmC5beaQXeQ2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAATAN +BgkqhkiG9w0BAQQFAANBAFqPEKFjk6T6CKTHvaQeEAsX0/8YHPHqH/9AnhSjrwuX +9EBc0n6bVGhN7XaXd6sJ7dym9sbsWxb+pJdurnkxjx4= +-----END CERTIFICATE----- Added: python/trunk/Lib/test/ssl_key.pem ============================================================================== --- (empty file) +++ python/trunk/Lib/test/ssl_key.pem Tue Apr 3 19:29:48 2007 @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBPAIBAAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNwL4lYKbpzzlmC5beaQXeQ +2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAAQJBALjkK+jc2+iihI98riEF +oudmkNziSRTYjnwjx8mCoAjPWviB3c742eO3FG4/soi1jD9A5alihEOXfUzloenr +8IECIQD3B5+0l+68BA/6d76iUNqAAV8djGTzvxnCxycnxPQydQIhAMXt4trUI3nc +a+U8YL2HPFA3gmhBsSICbq2OptOCnM7hAiEA6Xi3JIQECob8YwkRj29DU3/4WYD7 +WLPgsQpwo1GuSpECICGsnWH5oaeD9t9jbFoSfhJvv0IZmxdcLpRcpslpeWBBAiEA +6/5B8J0GHdJq89FHwEG/H2eVVUYu5y/aD6sgcm+0Avg= +-----END RSA PRIVATE KEY----- Modified: python/trunk/Lib/test/test_socket_ssl.py ============================================================================== --- python/trunk/Lib/test/test_socket_ssl.py (original) +++ python/trunk/Lib/test/test_socket_ssl.py Tue Apr 3 19:29:48 2007 @@ -8,6 +8,9 @@ import threading import subprocess import time +import ctypes +import os +import urllib # Optionally test SSL support, if we have it in the tested platform skip_expected = not hasattr(socket, "ssl") @@ -15,11 +18,6 @@ class ConnectedTests(unittest.TestCase): def testBasic(self): - import urllib - - if test_support.verbose: - print "test_basic ..." - socket.RAND_status() try: socket.RAND_egd(1) @@ -42,9 +40,6 @@ hoped for. If this message is seen often, test_timeout should be changed to use a more reliable address.""" % (ADDR, extra_msg) - if test_support.verbose: - print "test_timeout ..." - # A service which issues a welcome banner (without need to write # anything). # XXX ("gmail.org", 995) has been unreliable so far, from time to @@ -75,9 +70,6 @@ class BasicTests(unittest.TestCase): def testRudeShutdown(self): - if test_support.verbose: - print "test_rude_shutdown ..." - # Some random port to connect to. PORT = [9934] @@ -115,7 +107,68 @@ connector() t.join() +class OpenSSLTests(unittest.TestCase): + + def testBasic(self): + time.sleep(.2) + s = socket.socket() + s.connect(("localhost", 4433)) + ss = socket.ssl(s) + ss.write("Foo\n") + i = ss.read(4) + self.assertEqual(i, "Foo\n") + + +def haveOpenSSL(): + try: + s = subprocess.Popen("openssl rand 1".split(), stdout=subprocess.PIPE) + s.stdout.read(1) + except OSError, err: + if err.errno == 2: + return False + raise + return True + +class OpenSSLServer(threading.Thread): + def __init__(self): + self.s = None + self.keepServing = True + threading.Thread.__init__(self) + + def run(self): + if os.access("ssl_cert.pem", os.F_OK): + cert_file = "ssl_cert.pem" + elif os.access("./Lib/test/ssl_cert.pem", os.F_OK): + cert_file = "./Lib/test/ssl_cert.pem" + else: + raise ValueError("No cert file found!") + if os.access("ssl_key.pem", os.F_OK): + key_file = "ssl_key.pem" + elif os.access("./Lib/test/ssl_key.pem", os.F_OK): + key_file = "./Lib/test/ssl_key.pem" + else: + raise ValueError("No cert file found!") + cmd = "openssl s_server -cert %s -key %s -quiet" % (cert_file, key_file) + self.s = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + while self.keepServing: + time.sleep(.5) + l = self.s.stdout.readline() + self.s.stdin.write(l) + + def shutdown(self): + self.keepServing = False + if not self.s: + return + if sys.platform == "win32": + handle = ctypes.windll.kernel32.OpenProcess(1, False, self.s.pid) + ctypes.windll.kernel32.TerminateProcess(handle, -1) + ctypes.windll.kernel32.CloseHandle(handle) + else: + os.kill(self.s.pid, 15) + def test_main(): if not hasattr(socket, "ssl"): raise test_support.TestSkipped("socket module has no ssl support") @@ -125,9 +178,25 @@ if test_support.is_resource_enabled('network'): tests.append(ConnectedTests) + # in these platforms we can kill the openssl process + if sys.platform in ("sunos5", "darwin", "linux1", + "linux2", "win32", "hp-ux11"): + if haveOpenSSL(): + haveServer = True + tests.append(OpenSSLTests) + else: + haveServer = False + + if haveServer: + server = OpenSSLServer() + server.start() + thread_info = test_support.threading_setup() test_support.run_unittest(*tests) test_support.threading_cleanup(*thread_info) + if haveServer: + server.shutdown() + if __name__ == "__main__": test_main() From buildbot at python.org Tue Apr 3 20:27:19 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Apr 2007 18:27:19 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP trunk Message-ID: <20070403182719.75CF61E400E@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/356 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: facundo.batista,walter.doerwald Build had warnings: warnings test Excerpt from the test logfile: 5 tests failed: test_extcall test_os test_profile test_urllib test_urllib2net ====================================================================== ERROR: test_makedir (test.test_os.MakedirTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_os.py", line 384, in setUp os.mkdir(test_support.TESTFN) WindowsError: [Error 183] Cannot create a file when that file already exists: '@test' ====================================================================== ERROR: test_access (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_os.py", line 451, in test_access self.assertRaises(WindowsError, os.utime, test_support.TESTFN, 0) File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\unittest.py", line 329, in failUnlessRaises callableObj(*args, **kwargs) TypeError: utime() arg 2 must be a tuple (atime, mtime) ====================================================================== FAIL: test_traversal (test.test_os.WalkTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_os.py", line 313, in test_traversal self.assertEqual(len(all), 4) AssertionError: 5 != 4 ====================================================================== FAIL: test_chdir (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_os.py", line 442, in test_chdir self.assertRaises(WindowsError, os.chdir, test_support.TESTFN) AssertionError: WindowsError not raised sincerely, -The Buildbot From python-checkins at python.org Tue Apr 3 20:33:37 2007 From: python-checkins at python.org (walter.doerwald) Date: Tue, 3 Apr 2007 20:33:37 +0200 (CEST) Subject: [Python-checkins] r54677 - in python/trunk: Lib/test/test_structmembers.py Lib/test/test_support.py Lib/test/test_warnings.py Misc/NEWS Message-ID: <20070403183337.17E611E4008@bag.python.org> Author: walter.doerwald Date: Tue Apr 3 20:33:29 2007 New Revision: 54677 Modified: python/trunk/Lib/test/test_structmembers.py python/trunk/Lib/test/test_support.py python/trunk/Lib/test/test_warnings.py python/trunk/Misc/NEWS Log: Implement a contextmanager test.test_support.catch_warning that can be used to catch the last warning issued by the warning framework. Change test_warnings.py and test_structmembers.py to use this new contextmanager. Modified: python/trunk/Lib/test/test_structmembers.py ============================================================================== --- python/trunk/Lib/test/test_structmembers.py (original) +++ python/trunk/Lib/test/test_structmembers.py Tue Apr 3 20:33:29 2007 @@ -4,7 +4,7 @@ INT_MAX, INT_MIN, UINT_MAX, \ LONG_MAX, LONG_MIN, ULONG_MAX -import warnings, exceptions, unittest, test.test_warnings +import warnings, exceptions, unittest from test import test_support ts=test_structmembersType(1,2,3,4,5,6,7,8,9.99999,10.1010101010) @@ -39,34 +39,39 @@ ts.T_ULONG=ULONG_MAX self.assertEquals(ts.T_ULONG, ULONG_MAX) -class TestWarnings(test.test_warnings.CatchWarningTest): - def has_warned(self): - self.assertEqual(test.test_warnings.msg.category, - exceptions.RuntimeWarning.__name__) +class TestWarnings(unittest.TestCase): + def has_warned(self, w): + self.assert_(w.category is RuntimeWarning) def test_byte_max(self): - ts.T_BYTE=CHAR_MAX+1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_BYTE=CHAR_MAX+1 + self.has_warned(w) def test_byte_min(self): - ts.T_BYTE=CHAR_MIN-1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_BYTE=CHAR_MIN-1 + self.has_warned(w) def test_ubyte_max(self): - ts.T_UBYTE=UCHAR_MAX+1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_UBYTE=UCHAR_MAX+1 + self.has_warned(w) def test_short_max(self): - ts.T_SHORT=SHRT_MAX+1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_SHORT=SHRT_MAX+1 + self.has_warned(w) def test_short_min(self): - ts.T_SHORT=SHRT_MIN-1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_SHORT=SHRT_MIN-1 + self.has_warned(w) def test_ushort_max(self): - ts.T_USHORT=USHRT_MAX+1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_USHORT=USHRT_MAX+1 + self.has_warned(w) Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Tue Apr 3 20:33:29 2007 @@ -282,6 +282,42 @@ finally: warnings.filters = original_filters +class WarningMessage(object): + "Holds the result of the latest showwarning() call" + def __init__(self): + self.message = None + self.category = None + self.filename = None + self.lineno = None + + def _showwarning(self, message, category, filename, lineno, file=None): + self.message = message + self.category = category + self.filename = filename + self.lineno = lineno + + at contextlib.contextmanager +def catch_warning(): + """ + Guard the warnings filter from being permanently changed and record the + data of the last warning that has been issued. + + Use like this: + + with catch_warning as w: + warnings.warn("foo") + assert str(w.message) == "foo" + """ + warning = WarningMessage() + original_filters = warnings.filters[:] + original_showwarning = warnings.showwarning + warnings.showwarning = warning._showwarning + try: + yield warning + finally: + warnings.showwarning = original_showwarning + warnings.filters = original_filters + class EnvironmentVarGuard(object): """Class to help protect the environment variable properly. Can be used as Modified: python/trunk/Lib/test/test_warnings.py ============================================================================== --- python/trunk/Lib/test/test_warnings.py (original) +++ python/trunk/Lib/test/test_warnings.py Tue Apr 3 20:33:29 2007 @@ -5,121 +5,95 @@ import warning_tests -# The warnings module isn't easily tested, because it relies on module -# globals to store configuration information. setUp() and tearDown() -# preserve the current settings to avoid bashing them while running tests. - -# To capture the warning messages, a replacement for showwarning() is -# used to save warning information in a global variable. - -class WarningMessage: - "Holds results of latest showwarning() call" - pass - -def showwarning(message, category, filename, lineno, file=None): - msg.message = str(message) - msg.category = category.__name__ - msg.filename = os.path.basename(filename) - msg.lineno = lineno - -class CatchWarningTest(unittest.TestCase): - # base class used for catching warnings issued by the - # warning framework (this is reused by test_structmembers.py) - +class TestModule(unittest.TestCase): def setUp(self): - global msg - msg = WarningMessage() - self._filters = warnings.filters[:] - self._showwarning = warnings.showwarning - warnings.showwarning = showwarning - self.ignored = [w[2].__name__ for w in self._filters + self.ignored = [w[2].__name__ for w in warnings.filters if w[0]=='ignore' and w[1] is None and w[3] is None] - def tearDown(self): - warnings.filters = self._filters[:] - warnings.showwarning = self._showwarning - -class TestModule(CatchWarningTest): - def test_warn_default_category(self): - for i in range(4): - text = 'multi %d' %i # Different text on each call - warnings.warn(text) - self.assertEqual(msg.message, text) - self.assertEqual(msg.category, 'UserWarning') + with test_support.catch_warning() as w: + for i in range(4): + text = 'multi %d' %i # Different text on each call + warnings.warn(text) + self.assertEqual(str(w.message), text) + self.assert_(w.category is UserWarning) def test_warn_specific_category(self): - text = 'None' - for category in [DeprecationWarning, FutureWarning, - PendingDeprecationWarning, RuntimeWarning, - SyntaxWarning, UserWarning, Warning]: - if category.__name__ in self.ignored: - text = 'filtered out' + category.__name__ - warnings.warn(text, category) - self.assertNotEqual(msg.message, text) - else: - text = 'unfiltered %s' % category.__name__ - warnings.warn(text, category) - self.assertEqual(msg.message, text) - self.assertEqual(msg.category, category.__name__) + with test_support.catch_warning() as w: + text = 'None' + for category in [DeprecationWarning, FutureWarning, + PendingDeprecationWarning, RuntimeWarning, + SyntaxWarning, UserWarning, Warning]: + if category.__name__ in self.ignored: + text = 'filtered out' + category.__name__ + warnings.warn(text, category) + self.assertNotEqual(w.message, text) + else: + text = 'unfiltered %s' % category.__name__ + warnings.warn(text, category) + self.assertEqual(str(w.message), text) + self.assert_(w.category is category) def test_filtering(self): + with test_support.catch_warning() as w: + warnings.filterwarnings("error", "", Warning, "", 0) + self.assertRaises(UserWarning, warnings.warn, 'convert to error') - warnings.filterwarnings("error", "", Warning, "", 0) - self.assertRaises(UserWarning, warnings.warn, 'convert to error') + warnings.resetwarnings() + text = 'handle normally' + warnings.warn(text) + self.assertEqual(str(w.message), text) + self.assert_(w.category is UserWarning) + + warnings.filterwarnings("ignore", "", Warning, "", 0) + text = 'filtered out' + warnings.warn(text) + self.assertNotEqual(str(w.message), text) - warnings.resetwarnings() - text = 'handle normally' - warnings.warn(text) - self.assertEqual(msg.message, text) - self.assertEqual(msg.category, 'UserWarning') - - warnings.filterwarnings("ignore", "", Warning, "", 0) - text = 'filtered out' - warnings.warn(text) - self.assertNotEqual(msg.message, text) - - warnings.resetwarnings() - warnings.filterwarnings("error", "hex*", Warning, "", 0) - self.assertRaises(UserWarning, warnings.warn, 'hex/oct') - text = 'nonmatching text' - warnings.warn(text) - self.assertEqual(msg.message, text) - self.assertEqual(msg.category, 'UserWarning') + warnings.resetwarnings() + warnings.filterwarnings("error", "hex*", Warning, "", 0) + self.assertRaises(UserWarning, warnings.warn, 'hex/oct') + text = 'nonmatching text' + warnings.warn(text) + self.assertEqual(str(w.message), text) + self.assert_(w.category is UserWarning) def test_options(self): # Uses the private _setoption() function to test the parsing # of command-line warning arguments - self.assertRaises(warnings._OptionError, - warnings._setoption, '1:2:3:4:5:6') - self.assertRaises(warnings._OptionError, - warnings._setoption, 'bogus::Warning') - self.assertRaises(warnings._OptionError, - warnings._setoption, 'ignore:2::4:-5') - warnings._setoption('error::Warning::0') - self.assertRaises(UserWarning, warnings.warn, 'convert to error') + with test_support.guard_warnings_filter(): + self.assertRaises(warnings._OptionError, + warnings._setoption, '1:2:3:4:5:6') + self.assertRaises(warnings._OptionError, + warnings._setoption, 'bogus::Warning') + self.assertRaises(warnings._OptionError, + warnings._setoption, 'ignore:2::4:-5') + warnings._setoption('error::Warning::0') + self.assertRaises(UserWarning, warnings.warn, 'convert to error') def test_filename(self): - warning_tests.inner("spam1") - self.assertEqual(msg.filename, "warning_tests.py") - warning_tests.outer("spam2") - self.assertEqual(msg.filename, "warning_tests.py") + with test_support.catch_warning() as w: + warning_tests.inner("spam1") + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") + warning_tests.outer("spam2") + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") def test_stacklevel(self): # Test stacklevel argument # make sure all messages are different, so the warning won't be skipped - warning_tests.inner("spam3", stacklevel=1) - self.assertEqual(msg.filename, "warning_tests.py") - warning_tests.outer("spam4", stacklevel=1) - self.assertEqual(msg.filename, "warning_tests.py") - - warning_tests.inner("spam5", stacklevel=2) - self.assertEqual(msg.filename, "test_warnings.py") - warning_tests.outer("spam6", stacklevel=2) - self.assertEqual(msg.filename, "warning_tests.py") + with test_support.catch_warning() as w: + warning_tests.inner("spam3", stacklevel=1) + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") + warning_tests.outer("spam4", stacklevel=1) + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") + + warning_tests.inner("spam5", stacklevel=2) + self.assertEqual(os.path.basename(w.filename), "test_warnings.py") + warning_tests.outer("spam6", stacklevel=2) + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") - warning_tests.inner("spam7", stacklevel=9999) - self.assertEqual(msg.filename, "sys") + warning_tests.inner("spam7", stacklevel=9999) + self.assertEqual(os.path.basename(w.filename), "sys") def test_main(verbose=None): Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Apr 3 20:33:29 2007 @@ -713,6 +713,9 @@ - Fix bsddb test_basics.test06_Transactions to check the version number properly. +- test.test_support.catch_warning is a new context manager that can be used + to catch the warnings issued by the warning framework. + Tools ----- From buildbot at python.org Tue Apr 3 21:01:05 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Apr 2007 19:01:05 +0000 Subject: [Python-checkins] buildbot warnings in x86 W2k trunk Message-ID: <20070403190106.356041E4011@bag.python.org> The Buildbot has detected a new failure of x86 W2k trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520W2k%2520trunk/builds/185 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: walter.doerwald Build had warnings: warnings test Excerpt from the test logfile: 4 tests failed: test_os test_profile test_socket_ssl test_urllib ====================================================================== ERROR: test_makedir (test.test_os.MakedirTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 384, in setUp os.mkdir(test_support.TESTFN) WindowsError: [Error 183] Cannot create a file when that file already exists: '@test' ====================================================================== ERROR: test_access (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 451, in test_access self.assertRaises(WindowsError, os.utime, test_support.TESTFN, 0) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\unittest.py", line 329, in failUnlessRaises callableObj(*args, **kwargs) TypeError: utime() arg 2 must be a tuple (atime, mtime) ====================================================================== FAIL: test_traversal (test.test_os.WalkTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 313, in test_traversal self.assertEqual(len(all), 4) AssertionError: 5 != 4 ====================================================================== FAIL: test_chdir (test.test_os.Win32ErrorTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_os.py", line 442, in test_chdir self.assertRaises(WindowsError, os.chdir, test_support.TESTFN) AssertionError: WindowsError not raised ====================================================================== ERROR: testBasic (test.test_socket_ssl.OpenSSLTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_socket_ssl.py", line 115, in testBasic s.connect(("localhost", 4433)) File "", line 1, in connect error: (10061, 'Connection refused') Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 460, in __bootstrap self.run() File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_socket_ssl.py", line 144, in run raise ValueError("No cert file found!") ValueError: No cert file found! Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\threading.py", line 460, in __bootstrap self.run() File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_socket_ssl.py", line 144, in run raise ValueError("No cert file found!") ValueError: No cert file found! sincerely, -The Buildbot From python-checkins at python.org Tue Apr 3 23:15:37 2007 From: python-checkins at python.org (facundo.batista) Date: Tue, 3 Apr 2007 23:15:37 +0200 (CEST) Subject: [Python-checkins] r54678 - python/trunk/Lib/test/test_socket_ssl.py Message-ID: <20070403211537.527091E4031@bag.python.org> Author: facundo.batista Date: Tue Apr 3 23:15:34 2007 New Revision: 54678 Modified: python/trunk/Lib/test/test_socket_ssl.py Log: Changed the whole structure of startup and checking if the server is available. Hope to not get more false alarms. Modified: python/trunk/Lib/test/test_socket_ssl.py ============================================================================== --- python/trunk/Lib/test/test_socket_ssl.py (original) +++ python/trunk/Lib/test/test_socket_ssl.py Tue Apr 3 23:15:34 2007 @@ -110,32 +110,24 @@ class OpenSSLTests(unittest.TestCase): def testBasic(self): - time.sleep(.2) s = socket.socket() s.connect(("localhost", 4433)) ss = socket.ssl(s) ss.write("Foo\n") i = ss.read(4) self.assertEqual(i, "Foo\n") + s.close() -def haveOpenSSL(): - try: - s = subprocess.Popen("openssl rand 1".split(), stdout=subprocess.PIPE) - s.stdout.read(1) - except OSError, err: - if err.errno == 2: - return False - raise - return True - class OpenSSLServer(threading.Thread): def __init__(self): self.s = None self.keepServing = True - threading.Thread.__init__(self) + self._external() + if self.haveServer: + threading.Thread.__init__(self) - def run(self): + def _external(self): if os.access("ssl_cert.pem", os.F_OK): cert_file = "ssl_cert.pem" elif os.access("./Lib/test/ssl_cert.pem", os.F_OK): @@ -149,10 +141,27 @@ else: raise ValueError("No cert file found!") - cmd = "openssl s_server -cert %s -key %s -quiet" % (cert_file, key_file) - self.s = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, + try: + cmd = "openssl s_server -cert %s -key %s -quiet" % (cert_file, key_file) + self.s = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + time.sleep(1) + except: + self.haveServer = False + else: + # let's try if it is actually up + try: + s = socket.socket() + s.connect(("localhost", 4433)) + s.close() + assert self.s.stdout.readline() == "ERROR\n" + except: + self.haveServer = False + else: + self.haveServer = True + + def run(self): while self.keepServing: time.sleep(.5) l = self.s.stdout.readline() @@ -181,22 +190,23 @@ # in these platforms we can kill the openssl process if sys.platform in ("sunos5", "darwin", "linux1", "linux2", "win32", "hp-ux11"): - if haveOpenSSL(): - haveServer = True - tests.append(OpenSSLTests) - else: - haveServer = False - if haveServer: server = OpenSSLServer() - server.start() + if server.haveServer: + tests.append(OpenSSLTests) + server.start() + else: + server = None thread_info = test_support.threading_setup() - test_support.run_unittest(*tests) - test_support.threading_cleanup(*thread_info) - if haveServer: - server.shutdown() + try: + test_support.run_unittest(*tests) + finally: + if server is not None and server.haveServer: + server.shutdown() + + test_support.threading_cleanup(*thread_info) if __name__ == "__main__": test_main() From nnorwitz at gmail.com Tue Apr 3 23:38:35 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Tue, 3 Apr 2007 17:38:35 -0400 Subject: [Python-checkins] Python Regression Test Failures all (1) Message-ID: <20070403213835.GA7785@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 Exception in thread reader 4: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/tmp/python-test/local/lib/python2.6/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/tmp/python-test/local/lib/python2.6/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30996, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') Exception in thread reader 3: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/tmp/python-test/local/lib/python2.6/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/tmp/python-test/local/lib/python2.6/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30996, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') Exception in thread reader 2: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/tmp/python-test/local/lib/python2.6/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/tmp/python-test/local/lib/python2.6/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30996, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') Exception in thread writer 1: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/tmp/python-test/local/lib/python2.6/bsddb/test/test_thread.py", line 245, in writerThread self.assertEqual(data, self.makeData(key)) File "/tmp/python-test/local/lib/python2.6/unittest.py", line 343, in failUnlessEqual (msg or '%r != %r' % (first, second)) AssertionError: None != '1038-1038-1038-1038-1038' Exception in thread writer 0: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/tmp/python-test/local/lib/python2.6/bsddb/test/test_thread.py", line 260, in writerThread self.assertEqual(data, self.makeData(key)) File "/tmp/python-test/local/lib/python2.6/unittest.py", line 343, in failUnlessEqual (msg or '%r != %r' % (first, second)) AssertionError: None != '0002-0002-0002-0002-0002' Exception in thread writer 2: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/tmp/python-test/local/lib/python2.6/bsddb/test/test_thread.py", line 260, in writerThread self.assertEqual(data, self.makeData(key)) File "/tmp/python-test/local/lib/python2.6/unittest.py", line 343, in failUnlessEqual (msg or '%r != %r' % (first, second)) AssertionError: None != '2000-2000-2000-2000-2000' test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler testCompileLibrary still working, be patient... test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7325 refs] [7325 refs] [7325 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7700 refs] [7700 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test test_smtplib failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_smtplib.py", line 39, in testBasic smtp = smtplib.SMTP("localhost", 9091) File "/tmp/python-test/local/lib/python2.6/smtplib.py", line 248, in __init__ (code, msg) = self.connect(host, port) File "/tmp/python-test/local/lib/python2.6/smtplib.py", line 304, in connect self.sock = self._get_socket(host, port, self.timeout) File "/tmp/python-test/local/lib/python2.6/smtplib.py", line 282, in _get_socket return socket.create_connection((port, host), timeout) File "/tmp/python-test/local/lib/python2.6/socket.py", line 443, in create_connection raise error, msg error: (111, 'Connection refused') test_socket test_socket_ssl test_socketserver test test_socketserver crashed -- : (111, 'Connection refused') test_softspace test_sort test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7320 refs] [7321 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7321 refs] [8869 refs] [7536 refs] [7321 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] . [7320 refs] [7320 refs] this bit of output is from a test of stdout in a different process ... [7320 refs] [7320 refs] [7536 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7320 refs] [7320 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7324 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllibnet test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 301 tests OK. 2 tests failed: test_smtplib test_socketserver 21 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_cd test_cl test_gl test_imgfile test_ioctl test_macfs test_macostools test_pep277 test_plistlib test_scriptpackages test_startfile test_sunaudiodev test_tcl test_unicode_file test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl warning: DBTxn aborted in destructor. No prior commit() or abort(). [488836 refs] From buildbot at python.org Wed Apr 4 02:09:02 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Apr 2007 00:09:02 +0000 Subject: [Python-checkins] buildbot warnings in MIPS Debian trunk Message-ID: <20070404000903.156F31E4008@bag.python.org> The Buildbot has detected a new failure of MIPS Debian trunk. Full details are available at: http://www.python.org/dev/buildbot/all/MIPS%2520Debian%2520trunk/builds/732 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: facundo.batista,walter.doerwald Build had warnings: warnings test Excerpt from the test logfile: Traceback (most recent call last): File "./Lib/test/regrtest.py", line 1384, in main() File "./Lib/test/regrtest.py", line 416, in main e = _ExpectedSkips() File "./Lib/test/regrtest.py", line 1321, in __init__ from test import test_socket_ssl File "/home/pybot/buildarea/trunk.klose-debian-mips/build/Lib/test/test_socket_ssl.py", line 11, in import ctypes File "/home/pybot/buildarea/trunk.klose-debian-mips/build/Lib/ctypes/__init__.py", line 10, in from _ctypes import Union, Structure, Array ImportError: No module named _ctypes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Apr 4 02:17:13 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 4 Apr 2007 02:17:13 +0200 (CEST) Subject: [Python-checkins] r54679 - sandbox/trunk/abc/abc.py sandbox/trunk/abc/test_abc.py Message-ID: <20070404001713.1FD271E400A@bag.python.org> Author: guido.van.rossum Date: Wed Apr 4 02:17:12 2007 New Revision: 54679 Modified: sandbox/trunk/abc/abc.py sandbox/trunk/abc/test_abc.py Log: Move the index and slice helpers to global functions. Add proper slice support for AdaptToSequence. Modified: sandbox/trunk/abc/abc.py ============================================================================== --- sandbox/trunk/abc/abc.py (original) +++ sandbox/trunk/abc/abc.py Wed Apr 4 02:17:12 2007 @@ -406,6 +406,56 @@ ### SEQUENCES ### +def _index(i): + # Internal helper to raise TypeError for non-integer(-castable) values + if not isinstance(i, int): + if not hasattr(i, "__index__"): + raise TypeError + i = i.__index__() + if not isinstance(i, int): + raise TypeError + return i + + +def _slice(slc, size): + # Internal helper to normalize a slice into start, stop, step + # ints; arguments are a slice object and the length of the + # sequence. + # XXX A problem this shares with Python 2: a[n-1:-1:-1] (where n + # is len(a)) returns an empty slice because the stop value is + # normalized to n-1. + start, stop, step = slc.start, slc.stop, slc.step + + if start is not None: + start = _index(start) + if start < 0: + start += size + if stop is not None: + stop = _index(stop) + if stop < 0: + stop += size + if step is not None: + step = _index(step) + + if step is None: + step = 1 + if step == 0: + raise ValueError + if step < 0: + if start is None: + start = size - 1 + if stop is None: + stop = -1 + else: + if start is None: + start = 0 + if stop is None: + stop = size + + return start, stop, step + + + class Sequence(Sizeable, Iterable): """A minimal sequence. @@ -418,44 +468,14 @@ giving an iterable providing the elements. """ - def __index(self, i): - # Internal helper to raise TypeError for non-integer(-castable) values - if not isinstance(i, int): - if not hasattr(i, "__index__"): - raise TypeError - i = i.__index__() - if not isinstance(i, int): - raise TypeError - return i - @abstractmethod def __getitem__(self, index): if isinstance(index, slice): - return self.__getslice(index) - index = self.__index(index) - raise IndexError - - def __getslice(self, slc): - # XXX Would be nice to make this generally available? - start, stop, step = slc.start, slc.stop, slc.step - for index in start, stop, step: - if index is not None: - self.__index(index) - if step is None: - step = 1 - if step == 0: - raise ValueError - if step < 0: - if start is None: - start = len(self) - 1 - if stop is None: - stop = -1 + start, stop, step = _slice(index, len(self)) + return self.__class__(self[i] for i in range(start, stop, step)) else: - if start is None: - start = 0 - if stop is None: - stop = len(self) - return self.__class__(self[i] for i in range(start, stop, step)) + index = _index(index) + raise IndexError @abstractmethod def __len__(self): @@ -491,7 +511,7 @@ # XXX Looks like we need an ABC to indicate integer-ness... if not isinstance(repeat, int) and not hasattr(repeat, "__index__"): return NotImplemented - repeat = self.__index(repeat) + repeat = _index(repeat) return self.__class__(elem for i in range(repeat) for elem in self) def __eq__(self, other): @@ -555,12 +575,17 @@ class AdaptToSequence(Sequence): def __new__(cls, adaptee): - self = Sequence.__new__(cls) - self.adaptee = adaptee - return self + if not hasattr(adaptee, "__getitem__"): + # Hack so that the self.__class__() calls above work + adaptee = list(adaptee) + obj = Sequence.__new__(cls) + obj.adaptee = adaptee + return obj def __getitem__(self, index): - return self.adaptee[index] + if isinstance(index, slice): + return super(AdaptToSequence, self).__getitem__(index) + return self.adaptee[_index(index)] def __len__(self): return len(self.adaptee) Modified: sandbox/trunk/abc/test_abc.py ============================================================================== --- sandbox/trunk/abc/test_abc.py (original) +++ sandbox/trunk/abc/test_abc.py Wed Apr 4 02:17:12 2007 @@ -46,7 +46,9 @@ self.assertEqual(a[-1], 9) self.assertEqual(list(a), range(10)) #self.assertEqual(a, range(10)) - # Slicing isn't implemented correctly + b = a[1:-1] + self.assertEqual(b.__class__, abc.AdaptToSequence) + self.assertEqual(list(b), range(1, 9)) def test_adapt_to_mapping(self): a = abc.AdaptToMapping({1: 10, 2: 20}) From python-checkins at python.org Wed Apr 4 08:41:20 2007 From: python-checkins at python.org (georg.brandl) Date: Wed, 4 Apr 2007 08:41:20 +0200 (CEST) Subject: [Python-checkins] r54680 - peps/trunk/pep-0000.txt peps/trunk/pep-3117.txt Message-ID: <20070404064120.D10971E4005@bag.python.org> Author: georg.brandl Date: Wed Apr 4 08:41:20 2007 New Revision: 54680 Added: peps/trunk/pep-3117.txt Modified: peps/trunk/pep-0000.txt Log: Checkin PEP 3117. Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Wed Apr 4 08:41:20 2007 @@ -115,6 +115,7 @@ S 3108 Standard Library Reorganization Cannon S 3114 Renaming iterator.next() to iterator.__next__() Yee S 3116 New I/O Stutzbach, Verdone, GvR + S 3117 Postfix Type Declarations Brandl Finished PEPs (done, implemented in Subversion) @@ -468,6 +469,7 @@ S 3114 Renaming iterator.next() to iterator.__next__() Yee SA 3115 Metaclasses in Python 3000 Talin S 3116 New I/O Stutzbach, Verdone, GvR + S 3117 Postfix Type Declarations Brandl Key Added: peps/trunk/pep-3117.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-3117.txt Wed Apr 4 08:41:20 2007 @@ -0,0 +1,236 @@ +PEP: 3117 +Title: Postfix type declarations +Version: $Revision: $ +Last-Modified: $Date: $ +Author: Georg Brandl +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 01-Apr-2007 +Python-Version: 3.0 + + +Abstract +======== + +This PEP proposes the addition of a postfix type declaration syntax to +Python. It also specifies a new ``typedef`` statement which is used to create +new mappings between types and declarators. + +Its acceptance will greatly enhance the Python user experience as well as +eliminate one of the warts that deter users of other programming languages from +switching to Python. + + +Rationale +========= + +Python has long suffered from the lack of explicit type declarations. Being one +of the few aspects in which the language deviates from its Zen, this wart has +sparked many a discussion between Python heretics and members of the PSU (for +a few examples, see [EX1]_, [EX2]_ or [EX3]_), and it also made it a large-scale +enterprise success unlikely. + +However, if one wants to put an end to this misery, a decent Pythonic syntax +must be found. In almost all languages that have them, type declarations lack +this quality: they are verbose, often needing *multiple words* for a single +type, or they are hard to comprehend (e.g., a certain language uses completely +unrelated [#]_ adjectives like ``dim`` for type declaration). + +Therefore, this PEP combines the move to type declarations with another bold +move that will once again prove that Python is not only future-proof but +future-embracing: the introduction of Unicode characters as an integral +constituent of source code. + +Unicode makes it possible to express much more with much less characters, which +is in accordance with the Zen ("Readability counts.") [ZEN]_. Additionally, it +eliminates the need for a separate type declaration statement, and last but not +least, it makes Python measure up to Perl 6, which already uses Unicode for its +operators. [#]_ + + +Specification +============= + +When the type declaration mode is in operation, the grammar is changed so that +each ``NAME`` must consist of two parts: a name and a type declarator, which is +exactly one Unicode character. + +The declarator uniquely specifies the type of the name, and if it occurs on the +left hand side of an expression, this type is enforced: an ``InquisitionError`` +exception is raised if the returned type doesn't match the declared type. [#]_ + +Also, function call result types have to be specified. If the result of the call +does not have the declared type, an ``InquisitionError`` is raised. Caution: the +declarator for the result should not be confused with the declarator for the +function object (see the example below). + +Type declarators after names that are only read, not assigned to, are not strictly +necessary but enforced anyway (see the Python Zen: "Explicit is better than +implicit."). + +The mapping between types and declarators is not static. It can be completely +customized by the programmer, but for convenience there are some predefined +mappings for some built-in types: + +========================= =================================================== +Type Declarator +========================= =================================================== +``object`` ? (REPLACEMENT CHARACTER) +``int`` ? (DOUBLE-STRUCK CAPITAL N) +``float`` ? (ESTIMATED SYMBOL) +``bool`` ? (CHECK MARK) +``complex`` ? (DOUBLE-STRUCK CAPITAL C) +``str`` ? (LOWER RIGHT PENCIL) +``unicode`` ? (BLACK NIB) +``tuple`` ? (PARENTHESIZED LATIN SMALL LETTER T) +``list`` ? (HOT SPRINGS) +``dict`` ? (DOUBLE-ENDED MULTIMAP) +``set`` ? (EMPTY SET) (*Note:* this is also for full sets) +``frozenset`` ? (SNOWMAN) +``datetime`` ? (WATCH) +``function`` ? (LATIN SMALL LETTER LAMBDA WITH STROKE) +``generator`` ? (ATOM SYMBOL) +``Exception`` ? (ELECTRIC ARROW) +========================= =================================================== + +The declarator for the ``None`` type is a zero-width space. + +These characters should be obvious and easy to remember and type for every +programmer. + + +Unicode replacement units +========================= + +Since even in our modern, globalized world there are still some old-fashioned +rebels who can't or don't want to use Unicode in their source code, and since +Python is a forgiving language, a fallback is provided for those: + +Instead of the single Unicode character, they can type ``name${UNICODE NAME OF +THE DECLARATOR}$``. For example, these two function definitions are equivalent:: + + def foo?(x?): + return None + +and :: + + def foo${LATIN SMALL LETTER LAMBDA WITH STROKE}$(x${DOUBLE-STRUCK CAPITAL C}$): + return None${ZERO WIDTH NO-BREAK SPACE}$ + +This is still easy to read and makes the full power of type-annotated Python +available to ASCII believers. + + +The ``typedef`` statement +========================= + +The mapping between types and declarators can be extended with this new statement. + +The syntax is as follows:: + + typedef_stmt ::= "typedef" expr DECLARATOR + +where ``expr`` resolves to a type object. For convenience, the ``typedef`` statement +can also be mixed with the ``class`` statement for new classes, like so:: + + typedef class Foo?(object?): + pass + + +Example +======= + +This is the standard ``os.path.normpath`` function, converted to type declaration +syntax:: + + def normpath?(path?)?: + """Normalize path, eliminating double slashes, etc.""" + if path? == '': + return '.' + initial_slashes? = path?.startswith?('/')? + # POSIX allows one or two initial slashes, but treats three or more + # as single slash. + if (initial_slashes? and + path?.startswith?('//')? and not path?.startswith?('///')?)?: + initial_slashes? = 2 + comps? = path?.split?('/')? + new_comps? = []? + for comp? in comps?: + if comp? in ('', '.')?: + continue + if (comp? != '..' or (not initial_slashes? and not new_comps?)? or + (new_comps? and new_comps?[-1]? == '..')?)?: + new_comps?.append?(comp?) + elif new_comps?: + new_comps?.pop?()? + comps? = new_comps? + path? = '/'.join(comps?)? + if initial_slashes?: + path? = '/'*initial_slashes? + path? + return path? or '.' + +As you can clearly see, the type declarations add expressiveness, while at the +same time they make the code look much more professional. + + +Compatibility issues +==================== + +To enable type declaration mode, one has to write:: + + from __future__ import type_declarations + +which enables Unicode parsing of the source [#]_, makes ``typedef`` a keyword +and enforces correct types for all assignments and function calls. + + +References +========== + + +.. [EX1] http://mail.python.org/pipermail/python-list/2003-June/210588.html + +.. [EX2] http://mail.python.org/pipermail/python-list/2000-May/034685.html + +.. [EX3] http://groups.google.com/group/comp.lang.python/browse_frm/thread/6ae8c6add913635a/de40d4ffe9bd4304?lnk=gst&q=type+declarations&rnum=6 + +.. [#] Though, if you know the language in question, it may not be *that* unrelated. + +.. [ZEN] http://www.python.org/dev/peps/pep-0020/ + +.. [#] Well, it would, if there was a Perl 6. + +.. [#] Since the name ``TypeError`` is already in use, this name has been chosen + for obvious reasons. + +.. [#] The encoding in which the code is written is read from a standard coding + cookie. There will also be an autodetection mechanism, invoked by ``from + __future__ import encoding_hell``. + + +Acknowledgements +================ + +Many thanks go to Armin Ronacher, Alexander Schremmer and Marek Kubica who helped +find the most suitable and mnemonic declarator for built-in types. + +Thanks also to the Unicode Consortium for including all those useful characters +in the Unicode standard. + + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + coding: utf-8 + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + End: From nnorwitz at gmail.com Wed Apr 4 10:13:48 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Wed, 4 Apr 2007 04:13:48 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070404081348.GA774@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7325 refs] [7325 refs] [7325 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7700 refs] [7700 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 118, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 168, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7320 refs] [7321 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7321 refs] [8869 refs] [7536 refs] [7321 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] [7320 refs] . [7320 refs] [7320 refs] this bit of output is from a test of stdout in a different process ... [7320 refs] [7320 refs] [7536 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7320 refs] [7320 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7324 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [479173 refs] From python-checkins at python.org Wed Apr 4 16:10:40 2007 From: python-checkins at python.org (facundo.batista) Date: Wed, 4 Apr 2007 16:10:40 +0200 (CEST) Subject: [Python-checkins] r54681 - python/trunk/Lib/test/test_socket_ssl.py Message-ID: <20070404141040.CB0A11E4008@bag.python.org> Author: facundo.batista Date: Wed Apr 4 16:10:40 2007 New Revision: 54681 Modified: python/trunk/Lib/test/test_socket_ssl.py Log: Fixed the way that the .pem files are looked for, and changed how to kill the process in win32 to use the _handle attribute. Modified: python/trunk/Lib/test/test_socket_ssl.py ============================================================================== --- python/trunk/Lib/test/test_socket_ssl.py (original) +++ python/trunk/Lib/test/test_socket_ssl.py Wed Apr 4 16:10:40 2007 @@ -8,7 +8,6 @@ import threading import subprocess import time -import ctypes import os import urllib @@ -128,18 +127,14 @@ threading.Thread.__init__(self) def _external(self): - if os.access("ssl_cert.pem", os.F_OK): - cert_file = "ssl_cert.pem" - elif os.access("./Lib/test/ssl_cert.pem", os.F_OK): - cert_file = "./Lib/test/ssl_cert.pem" - else: - raise ValueError("No cert file found!") - if os.access("ssl_key.pem", os.F_OK): - key_file = "ssl_key.pem" - elif os.access("./Lib/test/ssl_key.pem", os.F_OK): - key_file = "./Lib/test/ssl_key.pem" - else: - raise ValueError("No cert file found!") + # let's find the .pem files + curdir = os.path.dirname(__file__) or os.curdir + cert_file = os.path.join(curdir, "ssl_cert.pem") + if not os.access(cert_file, os.F_OK): + raise ValueError("No cert file found! (tried %r)" % cert_file) + key_file = os.path.join(curdir, "ssl_key.pem") + if not os.access(key_file, os.F_OK): + raise ValueError("No key file found! (tried %r)" % key_file) try: cmd = "openssl s_server -cert %s -key %s -quiet" % (cert_file, key_file) @@ -172,9 +167,7 @@ if not self.s: return if sys.platform == "win32": - handle = ctypes.windll.kernel32.OpenProcess(1, False, self.s.pid) - ctypes.windll.kernel32.TerminateProcess(handle, -1) - ctypes.windll.kernel32.CloseHandle(handle) + subprocess.TerminateProcess(int(self.s._handle), -1) else: os.kill(self.s.pid, 15) From python-checkins at python.org Wed Apr 4 19:43:06 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 4 Apr 2007 19:43:06 +0200 (CEST) Subject: [Python-checkins] r54682 - python/trunk/Lib/test/test_socketserver.py Message-ID: <20070404174306.8E2DD1E4005@bag.python.org> Author: guido.van.rossum Date: Wed Apr 4 19:43:02 2007 New Revision: 54682 Modified: python/trunk/Lib/test/test_socketserver.py Log: Fix a race condition in this test -- instead of assuming that it will take the test server thread at most 0.5 seconds to get ready, use an event variable. Modified: python/trunk/Lib/test/test_socketserver.py ============================================================================== --- python/trunk/Lib/test/test_socketserver.py (original) +++ python/trunk/Lib/test/test_socketserver.py Wed Apr 4 19:43:02 2007 @@ -74,6 +74,7 @@ self.__addr = addr self.__svrcls = svrcls self.__hdlrcls = hdlrcls + self.ready = threading.Event() def run(self): class svrcls(MyMixinServer, self.__svrcls): pass @@ -87,6 +88,7 @@ if self.__addr != svr.socket.getsockname(): raise RuntimeError('server_address was %s, expected %s' % (self.__addr, svr.socket.getsockname())) + self.ready.set() if verbose: print "thread: serving three times" svr.serve_a_few() if verbose: print "thread: done" @@ -139,7 +141,9 @@ t.start() if verbose: print "server running" for i in range(NREQ): - time.sleep(DELAY) + t.ready.wait(10*DELAY) + if not t.ready.isSet(): + raise RuntimeError("Server not ready within a reasonable time") if verbose: print "test client", i testfunc(proto, addr) if verbose: print "waiting for server" From python-checkins at python.org Wed Apr 4 20:14:18 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 4 Apr 2007 20:14:18 +0200 (CEST) Subject: [Python-checkins] r54683 - python/trunk/Lib/test/test_dis.py Message-ID: <20070404181418.05C831E4005@bag.python.org> Author: collin.winter Date: Wed Apr 4 20:14:17 2007 New Revision: 54683 Modified: python/trunk/Lib/test/test_dis.py Log: Clean up imports. Modified: python/trunk/Lib/test/test_dis.py ============================================================================== --- python/trunk/Lib/test/test_dis.py (original) +++ python/trunk/Lib/test/test_dis.py Wed Apr 4 20:14:17 2007 @@ -1,11 +1,11 @@ -from test.test_support import verify, verbose, TestFailed, run_unittest +# Minimal tests for dis module + +from test.test_support import verbose, run_unittest +import unittest import sys import dis import StringIO -# Minimal tests for dis module - -import unittest def _f(a): print a From python-checkins at python.org Wed Apr 4 20:16:27 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 4 Apr 2007 20:16:27 +0200 (CEST) Subject: [Python-checkins] r54684 - python/trunk/Lib/test/test___all__.py Message-ID: <20070404181627.6616C1E4005@bag.python.org> Author: collin.winter Date: Wed Apr 4 20:16:24 2007 New Revision: 54684 Modified: python/trunk/Lib/test/test___all__.py Log: Stop using test_support.verify(). Modified: python/trunk/Lib/test/test___all__.py ============================================================================== --- python/trunk/Lib/test/test___all__.py (original) +++ python/trunk/Lib/test/test___all__.py Wed Apr 4 20:16:24 2007 @@ -1,7 +1,5 @@ import unittest -from test import test_support - -from test.test_support import verify, verbose +from test.test_support import verbose, run_unittest import sys import warnings @@ -22,15 +20,15 @@ # Silent fail here seems the best route since some modules # may not be available in all environments. return - verify(hasattr(sys.modules[modname], "__all__"), - "%s has no __all__ attribute" % modname) + self.failUnless(hasattr(sys.modules[modname], "__all__"), + "%s has no __all__ attribute" % modname) names = {} exec "from %s import *" % modname in names - if names.has_key("__builtins__"): + if "__builtins__" in names: del names["__builtins__"] keys = set(names) all = set(sys.modules[modname].__all__) - verify(keys==all, "%s != %s" % (keys, all)) + self.assertEqual(keys, all) def test_all(self): if not sys.platform.startswith('java'): @@ -181,7 +179,7 @@ def test_main(): - test_support.run_unittest(AllTest) + run_unittest(AllTest) if __name__ == "__main__": test_main() From python-checkins at python.org Wed Apr 4 20:30:42 2007 From: python-checkins at python.org (martin.v.loewis) Date: Wed, 4 Apr 2007 20:30:42 +0200 (CEST) Subject: [Python-checkins] r54685 - in python/trunk: Lib/test/test_os.py Misc/NEWS Modules/posixmodule.c Message-ID: <20070404183042.928261E400E@bag.python.org> Author: martin.v.loewis Date: Wed Apr 4 20:30:36 2007 New Revision: 54685 Modified: python/trunk/Lib/test/test_os.py python/trunk/Misc/NEWS python/trunk/Modules/posixmodule.c Log: Bug #1686475: Support stat'ing open files on Windows again. Will backport to 2.5. Modified: python/trunk/Lib/test/test_os.py ============================================================================== --- python/trunk/Lib/test/test_os.py (original) +++ python/trunk/Lib/test/test_os.py Wed Apr 4 20:30:36 2007 @@ -240,6 +240,15 @@ os.utime(self.fname, (t1, t1)) self.assertEquals(os.stat(self.fname).st_mtime, t1) + def test_1686475(self): + # Verify that an open file can be stat'ed + try: + os.stat(r"c:\pagefile.sys") + except WindowsError, e: + if e == 2: # file does not exist; cannot run test + return + self.fail("Could not stat pagefile.sys") + from test import mapping_tests class EnvironTests(mapping_tests.BasicTestMappingProtocol): Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Apr 4 20:30:36 2007 @@ -589,6 +589,8 @@ Extension Modules ----------------- +- Bug #1686475: Support stat'ing open files on Windows again. + - Patch #1185447: binascii.b2a_qp() now correctly quotes binary characters with ASCII value less than 32. Also, it correctly quotes dots only if they occur on a single line, as opposed to the previous behavior of Modified: python/trunk/Modules/posixmodule.c ============================================================================== --- python/trunk/Modules/posixmodule.c (original) +++ python/trunk/Modules/posixmodule.c Wed Apr 4 20:30:36 2007 @@ -844,14 +844,48 @@ *(FARPROC*)&gfaxw = GetProcAddress(hKernel32, "GetFileAttributesExW"); } +static BOOL +attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) +{ + HANDLE hFindFile; + WIN32_FIND_DATAA FileData; + hFindFile = FindFirstFileA(pszFile, &FileData); + if (hFindFile == INVALID_HANDLE_VALUE) + return FALSE; + FindClose(hFindFile); + pfad->dwFileAttributes = FileData.dwFileAttributes; + pfad->ftCreationTime = FileData.ftCreationTime; + pfad->ftLastAccessTime = FileData.ftLastAccessTime; + pfad->ftLastWriteTime = FileData.ftLastWriteTime; + pfad->nFileSizeHigh = FileData.nFileSizeHigh; + pfad->nFileSizeLow = FileData.nFileSizeLow; + return TRUE; +} + +static BOOL +attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) +{ + HANDLE hFindFile; + WIN32_FIND_DATAW FileData; + hFindFile = FindFirstFileW(pszFile, &FileData); + if (hFindFile == INVALID_HANDLE_VALUE) + return FALSE; + FindClose(hFindFile); + pfad->dwFileAttributes = FileData.dwFileAttributes; + pfad->ftCreationTime = FileData.ftCreationTime; + pfad->ftLastAccessTime = FileData.ftLastAccessTime; + pfad->ftLastWriteTime = FileData.ftLastWriteTime; + pfad->nFileSizeHigh = FileData.nFileSizeHigh; + pfad->nFileSizeLow = FileData.nFileSizeLow; + return TRUE; +} + static BOOL WINAPI Py_GetFileAttributesExA(LPCSTR pszFile, GET_FILEEX_INFO_LEVELS level, LPVOID pv) { BOOL result; - HANDLE hFindFile; - WIN32_FIND_DATAA FileData; LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv; /* First try to use the system's implementation, if that is available and either succeeds to gives an error other than @@ -873,17 +907,7 @@ accept). */ if (GetFileAttributesA(pszFile) == 0xFFFFFFFF) return FALSE; - hFindFile = FindFirstFileA(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - pfad->dwFileAttributes = FileData.dwFileAttributes; - pfad->ftCreationTime = FileData.ftCreationTime; - pfad->ftLastAccessTime = FileData.ftLastAccessTime; - pfad->ftLastWriteTime = FileData.ftLastWriteTime; - pfad->nFileSizeHigh = FileData.nFileSizeHigh; - pfad->nFileSizeLow = FileData.nFileSizeLow; - return TRUE; + return attributes_from_dir(pszFile, pfad); } static BOOL WINAPI @@ -892,8 +916,6 @@ LPVOID pv) { BOOL result; - HANDLE hFindFile; - WIN32_FIND_DATAW FileData; LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv; /* First try to use the system's implementation, if that is available and either succeeds to gives an error other than @@ -915,17 +937,7 @@ accept). */ if (GetFileAttributesW(pszFile) == 0xFFFFFFFF) return FALSE; - hFindFile = FindFirstFileW(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - pfad->dwFileAttributes = FileData.dwFileAttributes; - pfad->ftCreationTime = FileData.ftCreationTime; - pfad->ftLastAccessTime = FileData.ftLastAccessTime; - pfad->ftLastWriteTime = FileData.ftLastWriteTime; - pfad->nFileSizeHigh = FileData.nFileSizeHigh; - pfad->nFileSizeLow = FileData.nFileSizeLow; - return TRUE; + return attributes_from_dir_w(pszFile, pfad); } static int @@ -936,10 +948,20 @@ char *dot; /* XXX not supported on Win95 and NT 3.x */ if (!Py_GetFileAttributesExA(path, GetFileExInfoStandard, &info)) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; - return -1; + if (GetLastError() != ERROR_SHARING_VIOLATION) { + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; + } else { + /* Could not get attributes on open file. Fall back to + reading the directory. */ + if (!attributes_from_dir(path, &info)) { + /* Very strange. This should not fail now */ + errno = 0; + return -1; + } + } } code = attribute_data_to_stat(&info, result); if (code != 0) @@ -964,10 +986,20 @@ WIN32_FILE_ATTRIBUTE_DATA info; /* XXX not supported on Win95 and NT 3.x */ if (!Py_GetFileAttributesExW(path, GetFileExInfoStandard, &info)) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; - return -1; + if (GetLastError() != ERROR_SHARING_VIOLATION) { + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; + } else { + /* Could not get attributes on open file. Fall back to + reading the directory. */ + if (!attributes_from_dir_w(path, &info)) { + /* Very strange. This should not fail now */ + errno = 0; + return -1; + } + } } code = attribute_data_to_stat(&info, result); if (code < 0) From python-checkins at python.org Wed Apr 4 20:30:59 2007 From: python-checkins at python.org (martin.v.loewis) Date: Wed, 4 Apr 2007 20:30:59 +0200 (CEST) Subject: [Python-checkins] r54686 - in python/branches/release25-maint: Lib/test/test_os.py Misc/NEWS Modules/posixmodule.c Message-ID: <20070404183059.A048C1E400A@bag.python.org> Author: martin.v.loewis Date: Wed Apr 4 20:30:56 2007 New Revision: 54686 Modified: python/branches/release25-maint/Lib/test/test_os.py python/branches/release25-maint/Misc/NEWS python/branches/release25-maint/Modules/posixmodule.c Log: Bug #1686475: Support stat'ing open files on Windows again. Modified: python/branches/release25-maint/Lib/test/test_os.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_os.py (original) +++ python/branches/release25-maint/Lib/test/test_os.py Wed Apr 4 20:30:56 2007 @@ -231,6 +231,15 @@ os.utime(self.fname, (t1, t1)) self.assertEquals(os.stat(self.fname).st_mtime, t1) + def test_1686475(self): + # Verify that an open file can be stat'ed + try: + os.stat(r"c:\pagefile.sys") + except WindowsError, e: + if e == 2: # file does not exist; cannot run test + return + self.fail("Could not stat pagefile.sys") + from test import mapping_tests class EnvironTests(mapping_tests.BasicTestMappingProtocol): Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Wed Apr 4 20:30:56 2007 @@ -134,6 +134,8 @@ Extension Modules ----------------- +- Bug #1686475: Support stat'ing open files on Windows again. + - Bug #1647541: Array module's buffer interface can now handle empty arrays. - Bug #1693079: The array module can now successfully pickle empty arrays. Modified: python/branches/release25-maint/Modules/posixmodule.c ============================================================================== --- python/branches/release25-maint/Modules/posixmodule.c (original) +++ python/branches/release25-maint/Modules/posixmodule.c Wed Apr 4 20:30:56 2007 @@ -844,14 +844,48 @@ *(FARPROC*)&gfaxw = GetProcAddress(hKernel32, "GetFileAttributesExW"); } +static BOOL +attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) +{ + HANDLE hFindFile; + WIN32_FIND_DATAA FileData; + hFindFile = FindFirstFileA(pszFile, &FileData); + if (hFindFile == INVALID_HANDLE_VALUE) + return FALSE; + FindClose(hFindFile); + pfad->dwFileAttributes = FileData.dwFileAttributes; + pfad->ftCreationTime = FileData.ftCreationTime; + pfad->ftLastAccessTime = FileData.ftLastAccessTime; + pfad->ftLastWriteTime = FileData.ftLastWriteTime; + pfad->nFileSizeHigh = FileData.nFileSizeHigh; + pfad->nFileSizeLow = FileData.nFileSizeLow; + return TRUE; +} + +static BOOL +attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) +{ + HANDLE hFindFile; + WIN32_FIND_DATAW FileData; + hFindFile = FindFirstFileW(pszFile, &FileData); + if (hFindFile == INVALID_HANDLE_VALUE) + return FALSE; + FindClose(hFindFile); + pfad->dwFileAttributes = FileData.dwFileAttributes; + pfad->ftCreationTime = FileData.ftCreationTime; + pfad->ftLastAccessTime = FileData.ftLastAccessTime; + pfad->ftLastWriteTime = FileData.ftLastWriteTime; + pfad->nFileSizeHigh = FileData.nFileSizeHigh; + pfad->nFileSizeLow = FileData.nFileSizeLow; + return TRUE; +} + static BOOL WINAPI Py_GetFileAttributesExA(LPCSTR pszFile, GET_FILEEX_INFO_LEVELS level, LPVOID pv) { BOOL result; - HANDLE hFindFile; - WIN32_FIND_DATAA FileData; LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv; /* First try to use the system's implementation, if that is available and either succeeds to gives an error other than @@ -873,17 +907,7 @@ accept). */ if (GetFileAttributesA(pszFile) == 0xFFFFFFFF) return FALSE; - hFindFile = FindFirstFileA(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - pfad->dwFileAttributes = FileData.dwFileAttributes; - pfad->ftCreationTime = FileData.ftCreationTime; - pfad->ftLastAccessTime = FileData.ftLastAccessTime; - pfad->ftLastWriteTime = FileData.ftLastWriteTime; - pfad->nFileSizeHigh = FileData.nFileSizeHigh; - pfad->nFileSizeLow = FileData.nFileSizeLow; - return TRUE; + return attributes_from_dir(pszFile, pfad); } static BOOL WINAPI @@ -892,8 +916,6 @@ LPVOID pv) { BOOL result; - HANDLE hFindFile; - WIN32_FIND_DATAW FileData; LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv; /* First try to use the system's implementation, if that is available and either succeeds to gives an error other than @@ -915,17 +937,7 @@ accept). */ if (GetFileAttributesW(pszFile) == 0xFFFFFFFF) return FALSE; - hFindFile = FindFirstFileW(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - pfad->dwFileAttributes = FileData.dwFileAttributes; - pfad->ftCreationTime = FileData.ftCreationTime; - pfad->ftLastAccessTime = FileData.ftLastAccessTime; - pfad->ftLastWriteTime = FileData.ftLastWriteTime; - pfad->nFileSizeHigh = FileData.nFileSizeHigh; - pfad->nFileSizeLow = FileData.nFileSizeLow; - return TRUE; + return attributes_from_dir_w(pszFile, pfad); } static int @@ -936,10 +948,20 @@ char *dot; /* XXX not supported on Win95 and NT 3.x */ if (!Py_GetFileAttributesExA(path, GetFileExInfoStandard, &info)) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; - return -1; + if (GetLastError() != ERROR_SHARING_VIOLATION) { + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; + } else { + /* Could not get attributes on open file. Fall back to + reading the directory. */ + if (!attributes_from_dir(path, &info)) { + /* Very strange. This should not fail now */ + errno = 0; + return -1; + } + } } code = attribute_data_to_stat(&info, result); if (code != 0) @@ -964,10 +986,20 @@ WIN32_FILE_ATTRIBUTE_DATA info; /* XXX not supported on Win95 and NT 3.x */ if (!Py_GetFileAttributesExW(path, GetFileExInfoStandard, &info)) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; - return -1; + if (GetLastError() != ERROR_SHARING_VIOLATION) { + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; + } else { + /* Could not get attributes on open file. Fall back to + reading the directory. */ + if (!attributes_from_dir_w(path, &info)) { + /* Very strange. This should not fail now */ + errno = 0; + return -1; + } + } } code = attribute_data_to_stat(&info, result); if (code < 0) From python-checkins at python.org Wed Apr 4 20:33:44 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 4 Apr 2007 20:33:44 +0200 (CEST) Subject: [Python-checkins] r54687 - python/trunk/Lib/test/test_getopt.py Message-ID: <20070404183344.0616E1E4008@bag.python.org> Author: collin.winter Date: Wed Apr 4 20:33:40 2007 New Revision: 54687 Modified: python/trunk/Lib/test/test_getopt.py Log: Make test_getopt use unittest. Modified: python/trunk/Lib/test/test_getopt.py ============================================================================== --- python/trunk/Lib/test/test_getopt.py (original) +++ python/trunk/Lib/test/test_getopt.py Wed Apr 4 20:33:40 2007 @@ -1,180 +1,179 @@ # test_getopt.py # David Goodger 2000-08-19 +from test.test_support import verbose, run_doctest, run_unittest +import unittest + import getopt -from getopt import GetoptError -from test.test_support import verify, verbose, run_doctest import os -def expectException(teststr, expected, failure=AssertionError): - """Executes a statement passed in teststr, and raises an exception - (failure) if the expected exception is *not* raised.""" - try: - exec teststr - except expected: - pass - else: - raise failure - -old_posixly_correct = os.environ.get("POSIXLY_CORRECT") -if old_posixly_correct is not None: - del os.environ["POSIXLY_CORRECT"] - -if verbose: - print 'Running tests on getopt.short_has_arg' -verify(getopt.short_has_arg('a', 'a:')) -verify(not getopt.short_has_arg('a', 'a')) -expectException("tmp = getopt.short_has_arg('a', 'b')", GetoptError) -expectException("tmp = getopt.short_has_arg('a', '')", GetoptError) - -if verbose: - print 'Running tests on getopt.long_has_args' -has_arg, option = getopt.long_has_args('abc', ['abc=']) -verify(has_arg) -verify(option == 'abc') -has_arg, option = getopt.long_has_args('abc', ['abc']) -verify(not has_arg) -verify(option == 'abc') -has_arg, option = getopt.long_has_args('abc', ['abcd']) -verify(not has_arg) -verify(option == 'abcd') -expectException("has_arg, option = getopt.long_has_args('abc', ['def'])", - GetoptError) -expectException("has_arg, option = getopt.long_has_args('abc', [])", - GetoptError) -expectException("has_arg, option = " + \ - "getopt.long_has_args('abc', ['abcd','abcde'])", - GetoptError) - -if verbose: - print 'Running tests on getopt.do_shorts' -opts, args = getopt.do_shorts([], 'a', 'a', []) -verify(opts == [('-a', '')]) -verify(args == []) -opts, args = getopt.do_shorts([], 'a1', 'a:', []) -verify(opts == [('-a', '1')]) -verify(args == []) -#opts, args = getopt.do_shorts([], 'a=1', 'a:', []) -#verify(opts == [('-a', '1')]) -#verify(args == []) -opts, args = getopt.do_shorts([], 'a', 'a:', ['1']) -verify(opts == [('-a', '1')]) -verify(args == []) -opts, args = getopt.do_shorts([], 'a', 'a:', ['1', '2']) -verify(opts == [('-a', '1')]) -verify(args == ['2']) -expectException("opts, args = getopt.do_shorts([], 'a1', 'a', [])", - GetoptError) -expectException("opts, args = getopt.do_shorts([], 'a', 'a:', [])", - GetoptError) - -if verbose: - print 'Running tests on getopt.do_longs' -opts, args = getopt.do_longs([], 'abc', ['abc'], []) -verify(opts == [('--abc', '')]) -verify(args == []) -opts, args = getopt.do_longs([], 'abc=1', ['abc='], []) -verify(opts == [('--abc', '1')]) -verify(args == []) -opts, args = getopt.do_longs([], 'abc=1', ['abcd='], []) -verify(opts == [('--abcd', '1')]) -verify(args == []) -opts, args = getopt.do_longs([], 'abc', ['ab', 'abc', 'abcd'], []) -verify(opts == [('--abc', '')]) -verify(args == []) -# Much like the preceding, except with a non-alpha character ("-") in -# option name that precedes "="; failed in -# http://sourceforge.net/bugs/?func=detailbug&bug_id=126863&group_id=5470 -opts, args = getopt.do_longs([], 'foo=42', ['foo-bar', 'foo=',], []) -verify(opts == [('--foo', '42')]) -verify(args == []) -expectException("opts, args = getopt.do_longs([], 'abc=1', ['abc'], [])", - GetoptError) -expectException("opts, args = getopt.do_longs([], 'abc', ['abc='], [])", - GetoptError) - -# note: the empty string between '-a' and '--beta' is significant: -# it simulates an empty string option argument ('-a ""') on the command line. -cmdline = ['-a', '1', '-b', '--alpha=2', '--beta', '-a', '3', '-a', '', - '--beta', 'arg1', 'arg2'] - -if verbose: - print 'Running tests on getopt.getopt' -opts, args = getopt.getopt(cmdline, 'a:b', ['alpha=', 'beta']) -verify(opts == [('-a', '1'), ('-b', ''), ('--alpha', '2'), ('--beta', ''), - ('-a', '3'), ('-a', ''), ('--beta', '')] ) -# Note ambiguity of ('-b', '') and ('-a', '') above. This must be -# accounted for in the code that calls getopt(). -verify(args == ['arg1', 'arg2']) - -expectException( - "opts, args = getopt.getopt(cmdline, 'a:b', ['alpha', 'beta'])", - GetoptError) - -# Test handling of GNU style scanning mode. -if verbose: - print 'Running tests on getopt.gnu_getopt' -cmdline = ['-a', 'arg1', '-b', '1', '--alpha', '--beta=2'] -# GNU style -opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) -verify(opts == [('-a', ''), ('-b', '1'), ('--alpha', ''), ('--beta', '2')]) -verify(args == ['arg1']) -# Posix style via + -opts, args = getopt.gnu_getopt(cmdline, '+ab:', ['alpha', 'beta=']) -verify(opts == [('-a', '')]) -verify(args == ['arg1', '-b', '1', '--alpha', '--beta=2']) -# Posix style via POSIXLY_CORRECT -os.environ["POSIXLY_CORRECT"] = "1" -opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) -verify(opts == [('-a', '')]) -verify(args == ['arg1', '-b', '1', '--alpha', '--beta=2']) - - -if old_posixly_correct is None: - del os.environ["POSIXLY_CORRECT"] -else: - os.environ["POSIXLY_CORRECT"] = old_posixly_correct - -#------------------------------------------------------------------------------ - -libreftest = """ -Examples from the Library Reference: Doc/lib/libgetopt.tex - -An example using only Unix style options: - - ->>> import getopt ->>> args = '-a -b -cfoo -d bar a1 a2'.split() ->>> args -['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2'] ->>> optlist, args = getopt.getopt(args, 'abc:d:') ->>> optlist -[('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')] ->>> args -['a1', 'a2'] - -Using long option names is equally easy: - - ->>> s = '--condition=foo --testing --output-file abc.def -x a1 a2' ->>> args = s.split() ->>> args -['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2'] ->>> optlist, args = getopt.getopt(args, 'x', [ -... 'condition=', 'output-file=', 'testing']) ->>> optlist -[('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')] ->>> args -['a1', 'a2'] - -""" - -__test__ = {'libreftest' : libreftest} - -import sys -run_doctest(sys.modules[__name__], verbose) - -#------------------------------------------------------------------------------ +sentinel = object() -if verbose: - print "Module getopt: tests completed successfully." +class GetoptTests(unittest.TestCase): + def setUp(self): + self.old_posixly_correct = os.environ.get("POSIXLY_CORRECT", sentinel) + if self.old_posixly_correct is not sentinel: + del os.environ["POSIXLY_CORRECT"] + + def tearDown(self): + if self.old_posixly_correct is sentinel: + os.environ.pop("POSIXLY_CORRECT", None) + else: + os.environ["POSIXLY_CORRECT"] = self.old_posixly_correct + + def assertError(self, *args, **kwargs): + self.assertRaises(getopt.GetoptError, *args, **kwargs) + + def test_short_has_arg(self): + self.failUnless(getopt.short_has_arg('a', 'a:')) + self.failIf(getopt.short_has_arg('a', 'a')) + self.assertError(getopt.short_has_arg, 'a', 'b') + + def test_long_has_args(self): + has_arg, option = getopt.long_has_args('abc', ['abc=']) + self.failUnless(has_arg) + self.assertEqual(option, 'abc') + + has_arg, option = getopt.long_has_args('abc', ['abc']) + self.failIf(has_arg) + self.assertEqual(option, 'abc') + + has_arg, option = getopt.long_has_args('abc', ['abcd']) + self.failIf(has_arg) + self.assertEqual(option, 'abcd') + + self.assertError(getopt.long_has_args, 'abc', ['def']) + self.assertError(getopt.long_has_args, 'abc', []) + self.assertError(getopt.long_has_args, 'abc', ['abcd','abcde']) + + def test_do_shorts(self): + opts, args = getopt.do_shorts([], 'a', 'a', []) + self.assertEqual(opts, [('-a', '')]) + self.assertEqual(args, []) + + opts, args = getopt.do_shorts([], 'a1', 'a:', []) + self.assertEqual(opts, [('-a', '1')]) + self.assertEqual(args, []) + + #opts, args = getopt.do_shorts([], 'a=1', 'a:', []) + #self.assertEqual(opts, [('-a', '1')]) + #self.assertEqual(args, []) + + opts, args = getopt.do_shorts([], 'a', 'a:', ['1']) + self.assertEqual(opts, [('-a', '1')]) + self.assertEqual(args, []) + + opts, args = getopt.do_shorts([], 'a', 'a:', ['1', '2']) + self.assertEqual(opts, [('-a', '1')]) + self.assertEqual(args, ['2']) + + self.assertError(getopt.do_shorts, [], 'a1', 'a', []) + self.assertError(getopt.do_shorts, [], 'a', 'a:', []) + + def test_do_longs(self): + opts, args = getopt.do_longs([], 'abc', ['abc'], []) + self.assertEqual(opts, [('--abc', '')]) + self.assertEqual(args, []) + + opts, args = getopt.do_longs([], 'abc=1', ['abc='], []) + self.assertEqual(opts, [('--abc', '1')]) + self.assertEqual(args, []) + + opts, args = getopt.do_longs([], 'abc=1', ['abcd='], []) + self.assertEqual(opts, [('--abcd', '1')]) + self.assertEqual(args, []) + + opts, args = getopt.do_longs([], 'abc', ['ab', 'abc', 'abcd'], []) + self.assertEqual(opts, [('--abc', '')]) + self.assertEqual(args, []) + + # Much like the preceding, except with a non-alpha character ("-") in + # option name that precedes "="; failed in + # http://python.org/sf/126863 + opts, args = getopt.do_longs([], 'foo=42', ['foo-bar', 'foo=',], []) + self.assertEqual(opts, [('--foo', '42')]) + self.assertEqual(args, []) + + self.assertError(getopt.do_longs, [], 'abc=1', ['abc'], []) + self.assertError(getopt.do_longs, [], 'abc', ['abc='], []) + + def test_getopt(self): + # note: the empty string between '-a' and '--beta' is significant: + # it simulates an empty string option argument ('-a ""') on the + # command line. + cmdline = ['-a', '1', '-b', '--alpha=2', '--beta', '-a', '3', '-a', + '', '--beta', 'arg1', 'arg2'] + + opts, args = getopt.getopt(cmdline, 'a:b', ['alpha=', 'beta']) + self.assertEqual(opts, [('-a', '1'), ('-b', ''), + ('--alpha', '2'), ('--beta', ''), + ('-a', '3'), ('-a', ''), ('--beta', '')]) + # Note ambiguity of ('-b', '') and ('-a', '') above. This must be + # accounted for in the code that calls getopt(). + self.assertEqual(args, ['arg1', 'arg2']) + + self.assertError(getopt.getopt, cmdline, 'a:b', ['alpha', 'beta']) + + def test_gnu_getopt(self): + # Test handling of GNU style scanning mode. + cmdline = ['-a', 'arg1', '-b', '1', '--alpha', '--beta=2'] + + # GNU style + opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) + self.assertEqual(args, ['arg1']) + self.assertEqual(opts, [('-a', ''), ('-b', '1'), + ('--alpha', ''), ('--beta', '2')]) + + # Posix style via + + opts, args = getopt.gnu_getopt(cmdline, '+ab:', ['alpha', 'beta=']) + self.assertEqual(opts, [('-a', '')]) + self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2']) + + # Posix style via POSIXLY_CORRECT + os.environ["POSIXLY_CORRECT"] = "1" + opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) + self.assertEqual(opts, [('-a', '')]) + self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2']) + + def test_libref_examples(self): + s = """ + Examples from the Library Reference: Doc/lib/libgetopt.tex + + An example using only Unix style options: + + + >>> import getopt + >>> args = '-a -b -cfoo -d bar a1 a2'.split() + >>> args + ['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2'] + >>> optlist, args = getopt.getopt(args, 'abc:d:') + >>> optlist + [('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')] + >>> args + ['a1', 'a2'] + + Using long option names is equally easy: + + + >>> s = '--condition=foo --testing --output-file abc.def -x a1 a2' + >>> args = s.split() + >>> args + ['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2'] + >>> optlist, args = getopt.getopt(args, 'x', [ + ... 'condition=', 'output-file=', 'testing']) + >>> optlist + [('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')] + >>> args + ['a1', 'a2'] + """ + + import new + m = new.module("libreftest", s) + run_doctest(m, verbose) + + +def test_main(): + run_unittest(GetoptTests) + +if __name__ == "__main__": + test_main() From buildbot at python.org Wed Apr 4 20:36:01 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Apr 2007 18:36:01 +0000 Subject: [Python-checkins] buildbot failure in x86 OpenBSD 2.5 Message-ID: <20070404183601.6B1741E4005@bag.python.org> The Buildbot has detected a new failure of x86 OpenBSD 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520OpenBSD%25202.5/builds/244 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: martin.v.loewis BUILD FAILED: failed svn sincerely, -The Buildbot From python-checkins at python.org Wed Apr 4 20:36:31 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 4 Apr 2007 20:36:31 +0200 (CEST) Subject: [Python-checkins] r54688 - python/trunk/Lib/test/test_softspace.py Message-ID: <20070404183631.05C491E4005@bag.python.org> Author: collin.winter Date: Wed Apr 4 20:36:30 2007 New Revision: 54688 Modified: python/trunk/Lib/test/test_softspace.py Log: Make test_softspace use unittest. Modified: python/trunk/Lib/test/test_softspace.py ============================================================================== --- python/trunk/Lib/test/test_softspace.py (original) +++ python/trunk/Lib/test/test_softspace.py Wed Apr 4 20:36:30 2007 @@ -1,14 +1,23 @@ -from test import test_support +from test.test_support import run_unittest +import unittest import StringIO -# SF bug 480215: softspace confused in nested print -f = StringIO.StringIO() -class C: - def __str__(self): - print >> f, 'a' - return 'b' +class SoftspaceTests(unittest.TestCase): + def test_bug_480215(self): + # SF bug 480215: softspace confused in nested print + f = StringIO.StringIO() + class C: + def __str__(self): + print >> f, 'a' + return 'b' -print >> f, C(), 'c ', 'd\t', 'e' -print >> f, 'f', 'g' -# In 2.2 & earlier, this printed ' a\nbc d\te\nf g\n' -test_support.vereq(f.getvalue(), 'a\nb c d\te\nf g\n') + print >> f, C(), 'c ', 'd\t', 'e' + print >> f, 'f', 'g' + # In 2.2 & earlier, this printed ' a\nbc d\te\nf g\n' + self.assertEqual(f.getvalue(), 'a\nb c d\te\nf g\n') + +def test_main(): + run_unittest(SoftspaceTests) + +if __name__ == '__main__': + test_main() From python-checkins at python.org Wed Apr 4 20:38:47 2007 From: python-checkins at python.org (ziga.seilnacht) Date: Wed, 4 Apr 2007 20:38:47 +0200 (CEST) Subject: [Python-checkins] r54689 - python/trunk/Lib/test/test_os.py Message-ID: <20070404183847.F30EB1E4005@bag.python.org> Author: ziga.seilnacht Date: Wed Apr 4 20:38:47 2007 New Revision: 54689 Modified: python/trunk/Lib/test/test_os.py Log: Fix WalkTests.test_traversal() on Windows. The cleanup in MakedirTests.setUp() can now be removed. Modified: python/trunk/Lib/test/test_os.py ============================================================================== --- python/trunk/Lib/test/test_os.py (original) +++ python/trunk/Lib/test/test_os.py Wed Apr 4 20:38:47 2007 @@ -313,9 +313,9 @@ f.close() if hasattr(os, "symlink"): os.symlink(os.path.abspath(t2_path), link_path) + sub2_tree = (sub2_path, ["link"], ["tmp3"]) else: - # it must be a directory because the test expects that - os.mkdir(link_path) + sub2_tree = (sub2_path, [], ["tmp3"]) # Walk top-down. all = list(os.walk(walk_path)) @@ -328,7 +328,7 @@ self.assertEqual(all[0], (walk_path, ["SUB1", "SUB2"], ["tmp1"])) self.assertEqual(all[1 + flipped], (sub1_path, ["SUB11"], ["tmp2"])) self.assertEqual(all[2 + flipped], (sub11_path, [], [])) - self.assertEqual(all[3 - 2 * flipped], (sub2_path, ["link"], ["tmp3"])) + self.assertEqual(all[3 - 2 * flipped], sub2_tree) # Prune the search. all = [] @@ -340,7 +340,7 @@ dirs.remove('SUB1') self.assertEqual(len(all), 2) self.assertEqual(all[0], (walk_path, ["SUB2"], ["tmp1"])) - self.assertEqual(all[1], (sub2_path, ["link"], ["tmp3"])) + self.assertEqual(all[1], sub2_tree) # Walk bottom-up. all = list(os.walk(walk_path, topdown=False)) @@ -353,27 +353,28 @@ self.assertEqual(all[3], (walk_path, ["SUB1", "SUB2"], ["tmp1"])) self.assertEqual(all[flipped], (sub11_path, [], [])) self.assertEqual(all[flipped + 1], (sub1_path, ["SUB11"], ["tmp2"])) - self.assertEqual(all[2 - 2 * flipped], (sub2_path, ["link"], ["tmp3"])) + self.assertEqual(all[2 - 2 * flipped], sub2_tree) - # Walk, following symlinks. - for root, dirs, files in os.walk(walk_path, followlinks=True): - if root == link_path: - self.assertEqual(dirs, []) - self.assertEqual(files, ["tmp4"]) - break - else: - self.fail("Didn't follow symlink with followlinks=True") - + if hasattr(os, "symlink"): + # Walk, following symlinks. + for root, dirs, files in os.walk(walk_path, followlinks=True): + if root == link_path: + self.assertEqual(dirs, []) + self.assertEqual(files, ["tmp4"]) + break + else: + self.fail("Didn't follow symlink with followlinks=True") + def tearDown(self): # Tear everything down. This is a decent use for bottom-up on # Windows, which doesn't have a recursive delete command. The # (not so) subtlety is that rmdir will fail unless the dir's # kids are removed first, so bottom up is essential. for root, dirs, files in os.walk(test_support.TESTFN, topdown=False): for name in files: - os.remove(join(root, name)) + os.remove(os.path.join(root, name)) for name in dirs: - dirname = join(root, name) + dirname = os.path.join(root, name) if not os.path.islink(dirname): os.rmdir(dirname) else: @@ -382,14 +383,6 @@ class MakedirTests (unittest.TestCase): def setUp(self): - try: - os.rmdir(test_support.TESTFN) - except OSError: - pass - try: - os.unlink(test_support.TESTFN) - except OSError: - pass os.mkdir(test_support.TESTFN) def test_makedir(self): From buildbot at python.org Wed Apr 4 21:55:42 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Apr 2007 19:55:42 +0000 Subject: [Python-checkins] buildbot warnings in x86 W2k trunk Message-ID: <20070404195543.A0B751E400D@bag.python.org> The Buildbot has detected a new failure of x86 W2k trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520W2k%2520trunk/builds/190 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter,martin.v.loewis,ziga.seilnacht Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_urllib ====================================================================== ERROR: test_copy (test.test_urllib.urlretrieve_FileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_urllib.py", line 202, in test_copy test_support.TESTFN), second_temp) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\urllib.py", line 89, in urlretrieve return _urlopener.retrieve(url, filename, reporthook, data) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\urllib.py", line 225, in retrieve tfp = open(filename, 'wb') IOError: [Errno 13] Permission denied: '@test.2' ====================================================================== ERROR: test_reporthook (test.test_urllib.urlretrieve_FileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\test\test_urllib.py", line 227, in test_reporthook second_temp, hooktester) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\urllib.py", line 89, in urlretrieve return _urlopener.retrieve(url, filename, reporthook, data) File "C:\trentm\data\buildbot\python-slave\trunk.mick-windows\build\lib\urllib.py", line 225, in retrieve tfp = open(filename, 'wb') IOError: [Errno 13] Permission denied: '@test.2' sincerely, -The Buildbot From nnorwitz at gmail.com Wed Apr 4 22:13:42 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Wed, 4 Apr 2007 16:13:42 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070404201342.GA30702@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [479720 refs] From python-checkins at python.org Wed Apr 4 22:32:04 2007 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 4 Apr 2007 22:32:04 +0200 (CEST) Subject: [Python-checkins] r54690 - in python/branches/release25-maint: Lib/test/test_struct.py Misc/NEWS Modules/_struct.c Message-ID: <20070404203204.D19FE1E4002@bag.python.org> Author: raymond.hettinger Date: Wed Apr 4 22:32:03 2007 New Revision: 54690 Modified: python/branches/release25-maint/Lib/test/test_struct.py python/branches/release25-maint/Misc/NEWS python/branches/release25-maint/Modules/_struct.c Log: Bug #1563759: struct.unpack doens't support buffer protocol objects Modified: python/branches/release25-maint/Lib/test/test_struct.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_struct.py (original) +++ python/branches/release25-maint/Lib/test/test_struct.py Wed Apr 4 22:32:03 2007 @@ -612,8 +612,14 @@ assertRaises(struct.error, pack_into, small_buf, 0, test_string) assertRaises(struct.error, pack_into, small_buf, 2, test_string) +def test_unpack_with_buffer(): + # SF bug 1563759: struct.unpack doens't support buffer protocol objects + data = array.array('B', '\x12\x34\x56\x78') + value, = struct.unpack('>I', data) + vereq(value, 0x12345678) # Test methods to pack and unpack from buffers rather than strings. test_unpack_from() test_pack_into() test_pack_into_fn() +test_unpack_with_buffer() Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Wed Apr 4 22:32:03 2007 @@ -134,6 +134,8 @@ Extension Modules ----------------- +- Bug #1563759: struct.unpack doens't support buffer protocol objects + - Bug #1686475: Support stat'ing open files on Windows again. - Bug #1647541: Array module's buffer interface can now handle empty arrays. Modified: python/branches/release25-maint/Modules/_struct.c ============================================================================== --- python/branches/release25-maint/Modules/_struct.c (original) +++ python/branches/release25-maint/Modules/_struct.c Wed Apr 4 22:32:03 2007 @@ -1485,17 +1485,31 @@ static PyObject * s_unpack(PyObject *self, PyObject *inputstr) { + char *start; + int len; + PyObject * args; PyStructObject *soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->s_codes != NULL); - if (inputstr == NULL || !PyString_Check(inputstr) || - PyString_GET_SIZE(inputstr) != soself->s_size) { + if (inputstr != NULL && PyString_Check(inputstr) && + PyString_GET_SIZE(inputstr) == soself->s_size) { + return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); + } + args = PyTuple_Pack(1, inputstr); + if (args == NULL) + return NULL; + if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len)) { + Py_DECREF(args); + return NULL; + } + Py_DECREF(args); + if (soself->s_size != len) { PyErr_Format(StructError, "unpack requires a string argument of length %zd", soself->s_size); return NULL; } - return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); + return s_unpack_internal(soself, start); } PyDoc_STRVAR(s_unpack_from__doc__, From buildbot at python.org Wed Apr 4 22:47:44 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Apr 2007 20:47:44 +0000 Subject: [Python-checkins] buildbot warnings in amd64 gentoo 2.5 Message-ID: <20070404204744.493971E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%2520gentoo%25202.5/builds/270 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: raymond.hettinger Build had warnings: warnings test Excerpt from the test logfile: make: *** [buildbottest] Segmentation fault (core dumped) sincerely, -The Buildbot From buildbot at python.org Wed Apr 4 23:12:01 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Apr 2007 21:12:01 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP trunk Message-ID: <20070404211201.B8A061E4005@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/362 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter,martin.v.loewis,ziga.seilnacht Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_urllib ====================================================================== ERROR: test_copy (test.test_urllib.urlretrieve_FileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_urllib.py", line 202, in test_copy test_support.TESTFN), second_temp) File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\urllib.py", line 89, in urlretrieve return _urlopener.retrieve(url, filename, reporthook, data) File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\urllib.py", line 225, in retrieve tfp = open(filename, 'wb') IOError: [Errno 13] Permission denied: '@test.2' ====================================================================== ERROR: test_reporthook (test.test_urllib.urlretrieve_FileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\test\test_urllib.py", line 227, in test_reporthook second_temp, hooktester) File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\urllib.py", line 89, in urlretrieve return _urlopener.retrieve(url, filename, reporthook, data) File "C:\buildbot_py25\trunk.mcintyre-windows\build\lib\urllib.py", line 225, in retrieve tfp = open(filename, 'wb') IOError: [Errno 13] Permission denied: '@test.2' sincerely, -The Buildbot From buildbot at python.org Wed Apr 4 23:28:32 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Apr 2007 21:28:32 +0000 Subject: [Python-checkins] buildbot warnings in alpha Tru64 5.1 2.5 Message-ID: <20070404212832.BF6EB1E4002@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%25202.5/builds/238 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: raymond.hettinger Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_struct Traceback (most recent call last): File "./Lib/test/regrtest.py", line 549, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_struct.py", line 625, in test_unpack_with_buffer() File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_struct.py", line 618, in test_unpack_with_buffer value, = struct.unpack('>I', data) File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/struct.py", line 87, in unpack return o.unpack(s) error: unpack requires a string argument of length 4 sincerely, -The Buildbot From python-checkins at python.org Wed Apr 4 23:57:15 2007 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 4 Apr 2007 23:57:15 +0200 (CEST) Subject: [Python-checkins] r54691 - python/branches/release25-maint/Modules/_struct.c Message-ID: <20070404215715.009791E4002@bag.python.org> Author: raymond.hettinger Date: Wed Apr 4 23:57:12 2007 New Revision: 54691 Modified: python/branches/release25-maint/Modules/_struct.c Log: Fix-up error-exits on struct_unpack(). Modified: python/branches/release25-maint/Modules/_struct.c ============================================================================== --- python/branches/release25-maint/Modules/_struct.c (original) +++ python/branches/release25-maint/Modules/_struct.c Wed Apr 4 23:57:12 2007 @@ -1487,29 +1487,33 @@ { char *start; int len; - PyObject * args; + PyObject *args=NULL, *result; PyStructObject *soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->s_codes != NULL); - if (inputstr != NULL && PyString_Check(inputstr) && + if (inputstr == NULL) + goto fail; + if (PyString_Check(inputstr) && PyString_GET_SIZE(inputstr) == soself->s_size) { return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); } args = PyTuple_Pack(1, inputstr); if (args == NULL) return NULL; - if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len)) { - Py_DECREF(args); - return NULL; - } + if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len)) + goto fail; + if (soself->s_size != len) + goto fail; + result = s_unpack_internal(soself, start); Py_DECREF(args); - if (soself->s_size != len) { - PyErr_Format(StructError, - "unpack requires a string argument of length %zd", - soself->s_size); - return NULL; - } - return s_unpack_internal(soself, start); + return result; + +fail: + Py_XDECREF(args); + PyErr_Format(StructError, + "unpack requires a string argument of length %zd", + soself->s_size); + return NULL; } PyDoc_STRVAR(s_unpack_from__doc__, From python-checkins at python.org Thu Apr 5 06:52:07 2007 From: python-checkins at python.org (anthony.baxter) Date: Thu, 5 Apr 2007 06:52:07 +0200 (CEST) Subject: [Python-checkins] r54692 - in python/branches/release25-maint: Doc/commontex/boilerplate.tex Doc/commontex/license.tex Include/patchlevel.h LICENSE Lib/idlelib/NEWS.txt Lib/idlelib/idlever.py Misc/NEWS Misc/RPM/python-2.5.spec README Message-ID: <20070405045207.E94FD1E4002@bag.python.org> Author: anthony.baxter Date: Thu Apr 5 06:52:06 2007 New Revision: 54692 Modified: python/branches/release25-maint/Doc/commontex/boilerplate.tex python/branches/release25-maint/Doc/commontex/license.tex python/branches/release25-maint/Include/patchlevel.h python/branches/release25-maint/LICENSE python/branches/release25-maint/Lib/idlelib/NEWS.txt python/branches/release25-maint/Lib/idlelib/idlever.py python/branches/release25-maint/Misc/NEWS python/branches/release25-maint/Misc/RPM/python-2.5.spec python/branches/release25-maint/README Log: preparing for 2.5.1c1 Modified: python/branches/release25-maint/Doc/commontex/boilerplate.tex ============================================================================== --- python/branches/release25-maint/Doc/commontex/boilerplate.tex (original) +++ python/branches/release25-maint/Doc/commontex/boilerplate.tex Thu Apr 5 06:52:06 2007 @@ -5,5 +5,5 @@ Email: \email{docs at python.org} } -\date{19th September, 2006} % XXX update before final release! +\date{5th April, 2007} % XXX update before final release! \input{patchlevel} % include Python version information Modified: python/branches/release25-maint/Doc/commontex/license.tex ============================================================================== --- python/branches/release25-maint/Doc/commontex/license.tex (original) +++ python/branches/release25-maint/Doc/commontex/license.tex Thu Apr 5 06:52:06 2007 @@ -51,6 +51,7 @@ \linev{2.4.2}{2.4.1}{2005}{PSF}{yes} \linev{2.4.3}{2.4.2}{2006}{PSF}{yes} \linev{2.5}{2.4}{2006}{PSF}{yes} + \linev{2.5.1}{2.5}{2007}{PSF}{yes} \end{tablev} \note{GPL-compatible doesn't mean that we're distributing Modified: python/branches/release25-maint/Include/patchlevel.h ============================================================================== --- python/branches/release25-maint/Include/patchlevel.h (original) +++ python/branches/release25-maint/Include/patchlevel.h Thu Apr 5 06:52:06 2007 @@ -21,12 +21,12 @@ /* Version parsed out into numeric values */ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 5 -#define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL -#define PY_RELEASE_SERIAL 0 +#define PY_MICRO_VERSION 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "2.5" +#define PY_VERSION "2.5.1c1" /* Subversion Revision number of this file (not of the repository) */ #define PY_PATCHLEVEL_REVISION "$Revision$" Modified: python/branches/release25-maint/LICENSE ============================================================================== --- python/branches/release25-maint/LICENSE (original) +++ python/branches/release25-maint/LICENSE Thu Apr 5 06:52:06 2007 @@ -53,6 +53,7 @@ 2.4.2 2.4.1 2005 PSF yes 2.4.3 2.4.2 2006 PSF yes 2.5 2.4 2006 PSF yes + 2.5.1 2.5 2007 PSF yes Footnotes: Modified: python/branches/release25-maint/Lib/idlelib/NEWS.txt ============================================================================== --- python/branches/release25-maint/Lib/idlelib/NEWS.txt (original) +++ python/branches/release25-maint/Lib/idlelib/NEWS.txt Thu Apr 5 06:52:06 2007 @@ -1,3 +1,8 @@ +What's New in IDLE 1.2.1c1? +=========================== + +*Release date: 05-APR-2007* + What's New in IDLE 1.2? ======================= Modified: python/branches/release25-maint/Lib/idlelib/idlever.py ============================================================================== --- python/branches/release25-maint/Lib/idlelib/idlever.py (original) +++ python/branches/release25-maint/Lib/idlelib/idlever.py Thu Apr 5 06:52:06 2007 @@ -1 +1 @@ -IDLE_VERSION = "1.2" +IDLE_VERSION = "1.2.1c1" Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Thu Apr 5 06:52:06 2007 @@ -7,7 +7,7 @@ What's New in Python 2.5.1c1? ============================= -*Release date: XX-XXX-XXXX* +*Release date: 05-APR-2007* Core and builtins ----------------- Modified: python/branches/release25-maint/Misc/RPM/python-2.5.spec ============================================================================== --- python/branches/release25-maint/Misc/RPM/python-2.5.spec (original) +++ python/branches/release25-maint/Misc/RPM/python-2.5.spec Thu Apr 5 06:52:06 2007 @@ -33,7 +33,7 @@ ################################# %define name python -%define version 2.5 +%define version 2.5.1 %define libvers 2.5 %define release 1pydotorg %define __prefix /usr Modified: python/branches/release25-maint/README ============================================================================== --- python/branches/release25-maint/README (original) +++ python/branches/release25-maint/README Thu Apr 5 06:52:06 2007 @@ -1,5 +1,5 @@ -This is Python version 2.5 -========================== +This is Python version 2.5.1 +============================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation. From python-checkins at python.org Thu Apr 5 07:06:51 2007 From: python-checkins at python.org (neal.norwitz) Date: Thu, 5 Apr 2007 07:06:51 +0200 (CEST) Subject: [Python-checkins] r54693 - python/branches/release25-maint/Modules/_struct.c Message-ID: <20070405050651.D8E7C1E4002@bag.python.org> Author: neal.norwitz Date: Thu Apr 5 07:06:49 2007 New Revision: 54693 Modified: python/branches/release25-maint/Modules/_struct.c Log: Fix unpack so it works on 64-bit platforms. Modified: python/branches/release25-maint/Modules/_struct.c ============================================================================== --- python/branches/release25-maint/Modules/_struct.c (original) +++ python/branches/release25-maint/Modules/_struct.c Thu Apr 5 07:06:49 2007 @@ -1486,7 +1486,7 @@ s_unpack(PyObject *self, PyObject *inputstr) { char *start; - int len; + Py_ssize_t len; PyObject *args=NULL, *result; PyStructObject *soself = (PyStructObject *)self; assert(PyStruct_Check(self)); From nnorwitz at gmail.com Thu Apr 5 07:11:17 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Wed, 4 Apr 2007 22:11:17 -0700 Subject: [Python-checkins] r54693 - python/branches/release25-maint/Modules/_struct.c In-Reply-To: <20070405050651.D8E7C1E4002@bag.python.org> References: <20070405050651.D8E7C1E4002@bag.python.org> Message-ID: FYI Anthony approved this via IM. -- n On 4/4/07, neal.norwitz wrote: > Author: neal.norwitz > Date: Thu Apr 5 07:06:49 2007 > New Revision: 54693 > > Modified: > python/branches/release25-maint/Modules/_struct.c > Log: > Fix unpack so it works on 64-bit platforms. > > Modified: python/branches/release25-maint/Modules/_struct.c > ============================================================================== > --- python/branches/release25-maint/Modules/_struct.c (original) > +++ python/branches/release25-maint/Modules/_struct.c Thu Apr 5 07:06:49 2007 > @@ -1486,7 +1486,7 @@ > s_unpack(PyObject *self, PyObject *inputstr) > { > char *start; > - int len; > + Py_ssize_t len; > PyObject *args=NULL, *result; > PyStructObject *soself = (PyStructObject *)self; > assert(PyStruct_Check(self)); > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > From nnorwitz at gmail.com Thu Apr 5 07:20:07 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 5 Apr 2007 01:20:07 -0400 Subject: [Python-checkins] Python Regression Test Failures doc (1) Message-ID: <20070405052007.GA29217@python.psfb.org> TEXINPUTS=/home/neal/python/r25/Doc/commontex: python /home/neal/python/r25/Doc/tools/mkhowto --html --about html/stdabout.dat --iconserver ../icons --favicon ../icons/pyfav.png --address "See About this document... for information on suggesting changes." --up-link ../index.html --up-title "Python Documentation Index" --global-module-index "../modindex.html" --dvips-safe --dir html/api api/api.tex *** Session transcript and error messages are in /home/neal/python/r25/Doc/html/api/api.how. *** Exited with status 1. The relevant lines from the transcript are: ------------------------------------------------------------------------ +++ latex api This is TeX, Version 3.14159 (Web2C 7.4.5) (/home/neal/python/r25/Doc/api/api.tex LaTeX2e <2001/06/01> Babel and hyphenation patterns for american, french, german, ngerman, n ohyphenation, loaded. (/home/neal/python/r25/Doc/texinputs/manual.cls Document Class: manual 1998/03/03 Document class (Python manual) (/home/neal/python/r25/Doc/texinputs/pypaper.sty (/usr/share/texmf/tex/latex/psnfss/times.sty) Using Times instead of Computer Modern. ) (/usr/share/texmf/tex/latex/misc/fancybox.sty Style option: `fancybox' v1.3 <2000/09/19> (tvz) ) (/usr/share/texmf/tex/latex/base/report.cls Document Class: report 2001/04/21 v1.4e Standard LaTeX document class (/usr/share/texmf/tex/latex/base/size10.clo)) (/home/neal/python/r25/Doc/texinputs/fancyhdr.sty) Using fancier footers than usual. (/home/neal/python/r25/Doc/texinputs/fncychap.sty) Using fancy chapter headings. (/home/neal/python/r25/Doc/texinputs/python.sty (/usr/share/texmf/tex/latex/tools/longtable.sty) (/home/neal/python/r25/Doc/texinputs/underscore.sty) (/usr/share/texmf/tex/latex/tools/verbatim.sty) (/usr/share/texmf/tex/latex/base/alltt.sty))) (/home/neal/python/r25/Doc/commontex/boilerplate.tex ! LaTeX Error: Missing \begin{document}. See the LaTeX manual or LaTeX Companion for explanation. Type H for immediate help. ... l.8 < <<<<<< .mine ? ! Emergency stop. ... l.8 < <<<<<< .mine No pages of output. Transcript written on api.log. *** Session transcript and error messages are in /home/neal/python/r25/Doc/html/api/api.how. *** Exited with status 1. +++ TEXINPUTS=/home/neal/python/r25/Doc/api:/home/neal/python/r25/Doc/commontex:/home/neal/python/r25/Doc/paper-letter:/home/neal/python/r25/Doc/texinputs: +++ latex api make: *** [html/api/api.html] Error 1 From python-checkins at python.org Thu Apr 5 08:37:36 2007 From: python-checkins at python.org (anthony.baxter) Date: Thu, 5 Apr 2007 08:37:36 +0200 (CEST) Subject: [Python-checkins] r54694 - python/tags/r251c1 Message-ID: <20070405063736.5CD3A1E4014@bag.python.org> Author: anthony.baxter Date: Thu Apr 5 08:37:33 2007 New Revision: 54694 Added: python/tags/r251c1/ - copied from r54693, python/branches/release25-maint/ Log: Tagging for release of Python 2.5.1c1 From buildbot at python.org Thu Apr 5 08:50:15 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Apr 2007 06:50:15 +0000 Subject: [Python-checkins] buildbot warnings in alpha Tru64 5.1 2.5 Message-ID: <20070405065015.E27EA1E4002@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%25202.5/builds/241 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: neal.norwitz Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_signal Traceback (most recent call last): File "./Lib/test/regrtest.py", line 549, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_signal.py", line 143, in print "KeyboardInterrupt (the alarm() went off)" File "/net/ringneck/scratch1/nnorwitz/python/2.5.norwitz-tru64/build/Lib/test/test_signal.py", line 49, in handlerB raise HandlerBCalled, args HandlerBCalled: (30, ) sincerely, -The Buildbot From nnorwitz at gmail.com Thu Apr 5 10:13:42 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 5 Apr 2007 04:13:42 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070405081342.GA12607@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [479720 refs] From python-checkins at python.org Thu Apr 5 20:00:07 2007 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 5 Apr 2007 20:00:07 +0200 (CEST) Subject: [Python-checkins] r54695 - in python/trunk: Lib/test/test_struct.py Modules/_struct.c Message-ID: <20070405180007.98D751E400B@bag.python.org> Author: raymond.hettinger Date: Thu Apr 5 20:00:03 2007 New Revision: 54695 Modified: python/trunk/Lib/test/test_struct.py python/trunk/Modules/_struct.c Log: Bug #1563759: struct.unpack doens't support buffer protocol objects Modified: python/trunk/Lib/test/test_struct.py ============================================================================== --- python/trunk/Lib/test/test_struct.py (original) +++ python/trunk/Lib/test/test_struct.py Thu Apr 5 20:00:03 2007 @@ -614,11 +614,19 @@ assertRaises(struct.error, pack_into, small_buf, 0, test_string) assertRaises(struct.error, pack_into, small_buf, 2, test_string) +def test_unpack_with_buffer(): + # SF bug 1563759: struct.unpack doens't support buffer protocol objects + data1 = array.array('B', '\x12\x34\x56\x78') + data2 = buffer('......\x12\x34\x56\x78......', 6, 4) + for data in [data1, data2]: + value, = struct.unpack('>I', data) + vereq(value, 0x12345678) # Test methods to pack and unpack from buffers rather than strings. test_unpack_from() test_pack_into() test_pack_into_fn() +test_unpack_with_buffer() def test_bool(): for prefix in tuple("<>!=")+('',): Modified: python/trunk/Modules/_struct.c ============================================================================== --- python/trunk/Modules/_struct.c (original) +++ python/trunk/Modules/_struct.c Thu Apr 5 20:00:03 2007 @@ -1534,17 +1534,35 @@ static PyObject * s_unpack(PyObject *self, PyObject *inputstr) { + char *start; + Py_ssize_t len; + PyObject *args=NULL, *result; PyStructObject *soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->s_codes != NULL); - if (inputstr == NULL || !PyString_Check(inputstr) || - PyString_GET_SIZE(inputstr) != soself->s_size) { - PyErr_Format(StructError, - "unpack requires a string argument of length %zd", - soself->s_size); - return NULL; - } - return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); + if (inputstr == NULL) + goto fail; + if (PyString_Check(inputstr) && + PyString_GET_SIZE(inputstr) == soself->s_size) { + return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); + } + args = PyTuple_Pack(1, inputstr); + if (args == NULL) + return NULL; + if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len)) + goto fail; + if (soself->s_size != len) + goto fail; + result = s_unpack_internal(soself, start); + Py_DECREF(args); + return result; + +fail: + Py_XDECREF(args); + PyErr_Format(StructError, + "unpack requires a string argument of length %zd", + soself->s_size); + return NULL; } PyDoc_STRVAR(s_unpack_from__doc__, From python-checkins at python.org Thu Apr 5 20:25:15 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 5 Apr 2007 20:25:15 +0200 (CEST) Subject: [Python-checkins] r54696 - peps/trunk/pep-3116.txt Message-ID: <20070405182515.6C04B1E4002@bag.python.org> Author: guido.van.rossum Date: Thu Apr 5 20:25:11 2007 New Revision: 54696 Modified: peps/trunk/pep-3116.txt Log: Update by Mark Russell -- clarify readinto(), and qualify tell()/seek() on textio buffers. Modified: peps/trunk/pep-3116.txt ============================================================================== --- peps/trunk/pep-3116.txt (original) +++ peps/trunk/pep-3116.txt Thu Apr 5 20:25:11 2007 @@ -72,11 +72,11 @@ ``.readinto(b: bytes) -> int`` - Read up to ``n`` bytes from the object and stores them in + Read up to ``len(b)`` bytes from the object and stores them in ``b``, returning the number of bytes read. Like .read, fewer - than ``n`` bytes may be read, and 0 indicates end of file. + than ``len(b)`` bytes may be read, and 0 indicates end of file. ``None`` is returned if a non-blocking object has no bytes - available. + available. The length of ``b`` is never changed. ``.write(b: bytes) -> int`` @@ -100,7 +100,7 @@ ``.writable() -> bool`` - Returns ``True`` if the object was opened write writing, + Returns ``True`` if the object was opened for writing, ``False`` otherwise. If ``False``, ``.write()`` and ``.truncate()`` will raise an ``IOError`` if called. @@ -277,14 +277,32 @@ ``.write(s: str) -> None`` -``TextIOBase`` implementations also provide several methods that are -pass-throughs to the underlaying ``BufferedIOBase`` objects: + ``.tell() -> object`` - ``.seek(pos: int, whence: int = 0) -> None`` + Return a cookie describing the current file position. + The only supported use for the cookie is with .seek() + with whence set to 0 (i.e. absolute seek). - ``.tell() -> int`` + ``.seek(pos: object, whence: int = 0) -> None`` - ``.truncate(pos: int = None) -> None`` + Seek to position ``pos``. If ``pos`` is non-zero, it must + be a cookie returned from ``.tell()`` and ``whence`` must be zero. + + ``.truncate(pos: object = None) -> None`` + + Like ``BufferedIOBase.truncate()``, except that ``pos`` (if + not ``None``) must be a cookie previously returned by ``.tell()``. + +Unlike with raw I/O, the units for .seek() are not specified - some +implementations (e.g. ``StringIO``) use characters and others +(e.g. ``TextIOWrapper``) use bytes. The special case for zero is to +allow going to the start or end of a stream without a prior +``.tell()``. An implementation could include stream encoder state in +the cookie returned from ``.tell()``. + + +``TextIOBase`` implementations also provide several methods that are +pass-throughs to the underlaying ``BufferedIOBase`` objects: ``.flush() -> None`` From python-checkins at python.org Thu Apr 5 22:05:12 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 5 Apr 2007 22:05:12 +0200 (CEST) Subject: [Python-checkins] r54697 - python/trunk/Lib/test/test_long_future.py Message-ID: <20070405200512.1A17D1E4015@bag.python.org> Author: collin.winter Date: Thu Apr 5 22:05:07 2007 New Revision: 54697 Modified: python/trunk/Lib/test/test_long_future.py Log: Convert test_long_future to use unittest. Modified: python/trunk/Lib/test/test_long_future.py ============================================================================== --- python/trunk/Lib/test/test_long_future.py (original) +++ python/trunk/Lib/test/test_long_future.py Thu Apr 5 22:05:07 2007 @@ -3,53 +3,53 @@ # test_long.py instead. In the meantime, it's too obscure to try to # trick just part of test_long into using future division. -from test.test_support import TestFailed, verify, verbose +import unittest +from test.test_support import run_unittest -def test_true_division(): - if verbose: - print "long true division" - huge = 1L << 40000 - mhuge = -huge - verify(huge / huge == 1.0) - verify(mhuge / mhuge == 1.0) - verify(huge / mhuge == -1.0) - verify(mhuge / huge == -1.0) - verify(1 / huge == 0.0) - verify(1L / huge == 0.0) - verify(1 / mhuge == 0.0) - verify(1L / mhuge == 0.0) - verify((666 * huge + (huge >> 1)) / huge == 666.5) - verify((666 * mhuge + (mhuge >> 1)) / mhuge == 666.5) - verify((666 * huge + (huge >> 1)) / mhuge == -666.5) - verify((666 * mhuge + (mhuge >> 1)) / huge == -666.5) - verify(huge / (huge << 1) == 0.5) - verify((1000000 * huge) / huge == 1000000) - - namespace = {'huge': huge, 'mhuge': mhuge} - - for overflow in ["float(huge)", "float(mhuge)", - "huge / 1", "huge / 2L", "huge / -1", "huge / -2L", - "mhuge / 100", "mhuge / 100L"]: - try: - eval(overflow, namespace) - except OverflowError: - pass - else: - raise TestFailed("expected OverflowError from %r" % overflow) - - for underflow in ["1 / huge", "2L / huge", "-1 / huge", "-2L / huge", - "100 / mhuge", "100L / mhuge"]: - result = eval(underflow, namespace) - if result != 0.0: - raise TestFailed("expected underflow to 0 from %r" % underflow) - - for zero in ["huge / 0", "huge / 0L", - "mhuge / 0", "mhuge / 0L"]: - try: - eval(zero, namespace) - except ZeroDivisionError: - pass - else: - raise TestFailed("expected ZeroDivisionError from %r" % zero) - -test_true_division() +class TrueDivisionTests(unittest.TestCase): + def test(self): + huge = 1L << 40000 + mhuge = -huge + self.assertEqual(huge / huge, 1.0) + self.assertEqual(mhuge / mhuge, 1.0) + self.assertEqual(huge / mhuge, -1.0) + self.assertEqual(mhuge / huge, -1.0) + self.assertEqual(1 / huge, 0.0) + self.assertEqual(1L / huge, 0.0) + self.assertEqual(1 / mhuge, 0.0) + self.assertEqual(1L / mhuge, 0.0) + self.assertEqual((666 * huge + (huge >> 1)) / huge, 666.5) + self.assertEqual((666 * mhuge + (mhuge >> 1)) / mhuge, 666.5) + self.assertEqual((666 * huge + (huge >> 1)) / mhuge, -666.5) + self.assertEqual((666 * mhuge + (mhuge >> 1)) / huge, -666.5) + self.assertEqual(huge / (huge << 1), 0.5) + self.assertEqual((1000000 * huge) / huge, 1000000) + + namespace = {'huge': huge, 'mhuge': mhuge} + + for overflow in ["float(huge)", "float(mhuge)", + "huge / 1", "huge / 2L", "huge / -1", "huge / -2L", + "mhuge / 100", "mhuge / 100L"]: + # XXX(cwinter) this test doesn't pass when converted to + # use assertRaises. + try: + eval(overflow, namespace) + self.fail("expected OverflowError from %r" % overflow) + except OverflowError: + pass + + for underflow in ["1 / huge", "2L / huge", "-1 / huge", "-2L / huge", + "100 / mhuge", "100L / mhuge"]: + result = eval(underflow, namespace) + self.assertEqual(result, 0.0, + "expected underflow to 0 from %r" % underflow) + + for zero in ["huge / 0", "huge / 0L", "mhuge / 0", "mhuge / 0L"]: + self.assertRaises(ZeroDivisionError, eval, zero, namespace) + + +def test_main(): + run_unittest(TrueDivisionTests) + +if __name__ == "__main__": + test_main() From python-checkins at python.org Thu Apr 5 22:09:02 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 5 Apr 2007 22:09:02 +0200 (CEST) Subject: [Python-checkins] r54698 - python/trunk/Lib/test/test_normalization.py Message-ID: <20070405200902.BD8541E4005@bag.python.org> Author: collin.winter Date: Thu Apr 5 22:08:56 2007 New Revision: 54698 Modified: python/trunk/Lib/test/test_normalization.py Log: Convert test_normalization to use unittest. Modified: python/trunk/Lib/test/test_normalization.py ============================================================================== --- python/trunk/Lib/test/test_normalization.py (original) +++ python/trunk/Lib/test/test_normalization.py Thu Apr 5 22:08:56 2007 @@ -1,5 +1,6 @@ -from test.test_support import (verbose, TestFailed, TestSkipped, verify, - open_urlresource) +from test.test_support import run_unittest, open_urlresource +import unittest + import sys import os from unicodedata import normalize @@ -28,61 +29,66 @@ if x > sys.maxunicode: raise RangeError return u"".join([unichr(x) for x in data]) + +class NormalizationTest(unittest.TestCase): + def test_main(self): + part1_data = {} + for line in open_urlresource(TESTDATAURL): + if '#' in line: + line = line.split('#')[0] + line = line.strip() + if not line: + continue + if line.startswith("@Part"): + part = line.split()[0] + continue + if part == "@Part3": + # XXX we don't support PRI #29 yet, so skip these tests for now + continue + try: + c1,c2,c3,c4,c5 = [unistr(x) for x in line.split(';')[:-1]] + except RangeError: + # Skip unsupported characters; + # try atleast adding c1 if we are in part1 + if part == "@Part1": + try: + c1 = unistr(line.split(';')[0]) + except RangeError: + pass + else: + part1_data[c1] = 1 + continue + + # Perform tests + self.failUnless(c2 == NFC(c1) == NFC(c2) == NFC(c3), line) + self.failUnless(c4 == NFC(c4) == NFC(c5), line) + self.failUnless(c3 == NFD(c1) == NFD(c2) == NFD(c3), line) + self.failUnless(c5 == NFD(c4) == NFD(c5), line) + self.failUnless(c4 == NFKC(c1) == NFKC(c2) == \ + NFKC(c3) == NFKC(c4) == NFKC(c5), + line) + self.failUnless(c5 == NFKD(c1) == NFKD(c2) == \ + NFKD(c3) == NFKD(c4) == NFKD(c5), + line) -def test_main(): - part1_data = {} - for line in open_urlresource(TESTDATAURL): - if '#' in line: - line = line.split('#')[0] - line = line.strip() - if not line: - continue - if line.startswith("@Part"): - part = line.split()[0] - continue - if part == "@Part3": - # XXX we don't support PRI #29 yet, so skip these tests for now - continue - try: - c1,c2,c3,c4,c5 = [unistr(x) for x in line.split(';')[:-1]] - except RangeError: - # Skip unsupported characters; - # try atleast adding c1 if we are in part1 + # Record part 1 data if part == "@Part1": - try: - c1=unistr(line.split(';')[0]) - except RangeError: - pass - else: - part1_data[c1] = 1 - continue - - if verbose: - print line - - # Perform tests - verify(c2 == NFC(c1) == NFC(c2) == NFC(c3), line) - verify(c4 == NFC(c4) == NFC(c5), line) - verify(c3 == NFD(c1) == NFD(c2) == NFD(c3), line) - verify(c5 == NFD(c4) == NFD(c5), line) - verify(c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5), - line) - verify(c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5), - line) - - # Record part 1 data - if part == "@Part1": - part1_data[c1] = 1 - - # Perform tests for all other data - for c in range(sys.maxunicode+1): - X = unichr(c) - if X in part1_data: - continue - assert X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X), c + part1_data[c1] = 1 + + # Perform tests for all other data + for c in range(sys.maxunicode+1): + X = unichr(c) + if X in part1_data: + continue + self.failUnless(X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X), c) + + def test_bug_834676(self): + # Check for bug 834676 + normalize('NFC', u'\ud55c\uae00') - # Check for bug 834676 - normalize('NFC',u'\ud55c\uae00') + +def test_main(): + run_unittest(NormalizationTest) if __name__ == "__main__": test_main() From nnorwitz at gmail.com Thu Apr 5 22:13:46 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 5 Apr 2007 16:13:46 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070405201346.GA17628@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [479722 refs] From python-checkins at python.org Fri Apr 6 03:12:00 2007 From: python-checkins at python.org (andrew.kuchling) Date: Fri, 6 Apr 2007 03:12:00 +0200 (CEST) Subject: [Python-checkins] r54699 - python/trunk/Doc/lib/libctypes.tex Message-ID: <20070406011200.DE71F1E4003@bag.python.org> Author: andrew.kuchling Date: Fri Apr 6 03:11:58 2007 New Revision: 54699 Modified: python/trunk/Doc/lib/libctypes.tex Log: Some grammar fixes Modified: python/trunk/Doc/lib/libctypes.tex ============================================================================== --- python/trunk/Doc/lib/libctypes.tex (original) +++ python/trunk/Doc/lib/libctypes.tex Fri Apr 6 03:11:58 2007 @@ -7,21 +7,21 @@ \versionadded{2.5} \code{ctypes} is a foreign function library for Python. It provides C -compatible data types, and allows to call functions in dlls/shared +compatible data types, and allows calling functions in dlls/shared libraries. It can be used to wrap these libraries in pure Python. \subsection{ctypes tutorial\label{ctypes-ctypes-tutorial}} -Note: The code samples in this tutorial uses \code{doctest} to make sure +Note: The code samples in this tutorial use \code{doctest} to make sure that they actually work. Since some code samples behave differently under Linux, Windows, or Mac OS X, they contain doctest directives in comments. -Note: Quite some code samples references the ctypes \class{c{\_}int} type. +Note: Some code sample references the ctypes \class{c{\_}int} type. This type is an alias to the \class{c{\_}long} type on 32-bit systems. So, you should not be confused if \class{c{\_}long} is printed if you would -expect \class{c{\_}int} - they are actually the same type. +expect \class{c{\_}int} --- they are actually the same type. \subsubsection{Loading dynamic link libraries\label{ctypes-loading-dynamic-link-libraries}} @@ -38,7 +38,7 @@ automatically raise \class{WindowsError} Python exceptions when the function call fails. -Here are some examples for Windows, note that \code{msvcrt} is the MS +Here are some examples for Windows. Note that \code{msvcrt} is the MS standard C library containing most standard C functions, and uses the cdecl calling convention: \begin{verbatim} From nnorwitz at gmail.com Fri Apr 6 10:13:55 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Fri, 6 Apr 2007 04:13:55 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070406081355.GA24121@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [479971 refs] From python-checkins at python.org Fri Apr 6 17:09:23 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 6 Apr 2007 17:09:23 +0200 (CEST) Subject: [Python-checkins] r54700 - peps/trunk/pep-0008.txt Message-ID: <20070406150923.3CD6D1E4003@bag.python.org> Author: guido.van.rossum Date: Fri Apr 6 17:09:21 2007 New Revision: 54700 Modified: peps/trunk/pep-0008.txt Log: Add words discouraging overly-broad except clauses. Modified: peps/trunk/pep-0008.txt ============================================================================== --- peps/trunk/pep-0008.txt (original) +++ peps/trunk/pep-0008.txt Fri Apr 6 17:09:21 2007 @@ -689,6 +689,28 @@ the exception propagate upwards with 'raise'. 'try...finally' is a better way to handle this case. + - Additionally, for all try/except clauses, limit the 'try' clause + to the absolute minimum amount of code necessary. Again, this + avoids masking bugs. + + Yes: + + try: + value = collection[key] + except KeyError: + return key_not_found(key) + else: + return handle_value(value) + + No: + + try: + # Too broad! + return handle_value(collection[key]) + except KeyError: + # Will also catch KeyError raised by handle_value() + return key_not_found(key) + - Use string methods instead of the string module. String methods are always much faster and share the same API with From brett at python.org Fri Apr 6 20:27:19 2007 From: brett at python.org (Brett Cannon) Date: Fri, 6 Apr 2007 11:27:19 -0700 Subject: [Python-checkins] Python Regression Test Failures opt (1) In-Reply-To: <20070406081355.GA24121@python.psfb.org> References: <20070406081355.GA24121@python.psfb.org> Message-ID: On 4/6/07, Neal Norwitz wrote: > > [SNIP] > test_socket_ssl > test test_socket_ssl failed -- Traceback (most recent call last): > File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", > line 117, in testBasic > self.assertEqual(i, "Foo\n") > AssertionError: 'ERRO' != 'Foo\n' > > test_socketserver > test_socketserver skipped -- Use of the `network' resource not enabled > test_softspace > test_sort > Exception in thread Thread-43: > Traceback (most recent call last): > File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in > __bootstrap > self.run() > File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", > line 163, in run > self.s.stdin.write(l) > IOError: [Errno 32] Broken pipe Anyone know what caused these two tests to start failing? -Brett -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/python-checkins/attachments/20070406/0f2cc124/attachment.html From python-checkins at python.org Fri Apr 6 21:27:44 2007 From: python-checkins at python.org (collin.winter) Date: Fri, 6 Apr 2007 21:27:44 +0200 (CEST) Subject: [Python-checkins] r54704 - python/trunk/Lib/test/test_stringprep.py Message-ID: <20070406192744.ED21C1E4012@bag.python.org> Author: collin.winter Date: Fri Apr 6 21:27:40 2007 New Revision: 54704 Modified: python/trunk/Lib/test/test_stringprep.py Log: Convert test_stringprep to use unittest. Modified: python/trunk/Lib/test/test_stringprep.py ============================================================================== --- python/trunk/Lib/test/test_stringprep.py (original) +++ python/trunk/Lib/test/test_stringprep.py Fri Apr 6 21:27:40 2007 @@ -1,88 +1,96 @@ # To fully test this module, we would need a copy of the stringprep tables. # Since we don't have them, this test checks only a few codepoints. -from test.test_support import verify, vereq +import unittest +from test import test_support -import stringprep from stringprep import * -verify(in_table_a1(u"\u0221")) -verify(not in_table_a1(u"\u0222")) - -verify(in_table_b1(u"\u00ad")) -verify(not in_table_b1(u"\u00ae")) - -verify(map_table_b2(u"\u0041"), u"\u0061") -verify(map_table_b2(u"\u0061"), u"\u0061") - -verify(map_table_b3(u"\u0041"), u"\u0061") -verify(map_table_b3(u"\u0061"), u"\u0061") - -verify(in_table_c11(u"\u0020")) -verify(not in_table_c11(u"\u0021")) - -verify(in_table_c12(u"\u00a0")) -verify(not in_table_c12(u"\u00a1")) - -verify(in_table_c12(u"\u00a0")) -verify(not in_table_c12(u"\u00a1")) - -verify(in_table_c11_c12(u"\u00a0")) -verify(not in_table_c11_c12(u"\u00a1")) - -verify(in_table_c21(u"\u001f")) -verify(not in_table_c21(u"\u0020")) - -verify(in_table_c22(u"\u009f")) -verify(not in_table_c22(u"\u00a0")) - -verify(in_table_c21_c22(u"\u009f")) -verify(not in_table_c21_c22(u"\u00a0")) - -verify(in_table_c3(u"\ue000")) -verify(not in_table_c3(u"\uf900")) - -verify(in_table_c4(u"\uffff")) -verify(not in_table_c4(u"\u0000")) - -verify(in_table_c5(u"\ud800")) -verify(not in_table_c5(u"\ud7ff")) - -verify(in_table_c6(u"\ufff9")) -verify(not in_table_c6(u"\ufffe")) - -verify(in_table_c7(u"\u2ff0")) -verify(not in_table_c7(u"\u2ffc")) - -verify(in_table_c8(u"\u0340")) -verify(not in_table_c8(u"\u0342")) - -# C.9 is not in the bmp -# verify(in_table_c9(u"\U000E0001")) -# verify(not in_table_c8(u"\U000E0002")) - -verify(in_table_d1(u"\u05be")) -verify(not in_table_d1(u"\u05bf")) - -verify(in_table_d2(u"\u0041")) -verify(not in_table_d2(u"\u0040")) - -# This would generate a hash of all predicates. However, running -# it is quite expensive, and only serves to detect changes in the -# unicode database. Instead, stringprep.py asserts the version of -# the database. - -# import hashlib -# predicates = [k for k in dir(stringprep) if k.startswith("in_table")] -# predicates.sort() -# for p in predicates: -# f = getattr(stringprep, p) -# # Collect all BMP code points -# data = ["0"] * 0x10000 -# for i in range(0x10000): -# if f(unichr(i)): -# data[i] = "1" -# data = "".join(data) -# h = hashlib.sha1() -# h.update(data) -# print p, h.hexdigest() +class StringprepTests(unittest.TestCase): + def test(self): + self.failUnless(in_table_a1(u"\u0221")) + self.failIf(in_table_a1(u"\u0222")) + + self.failUnless(in_table_b1(u"\u00ad")) + self.failIf(in_table_b1(u"\u00ae")) + + self.failUnless(map_table_b2(u"\u0041"), u"\u0061") + self.failUnless(map_table_b2(u"\u0061"), u"\u0061") + + self.failUnless(map_table_b3(u"\u0041"), u"\u0061") + self.failUnless(map_table_b3(u"\u0061"), u"\u0061") + + self.failUnless(in_table_c11(u"\u0020")) + self.failIf(in_table_c11(u"\u0021")) + + self.failUnless(in_table_c12(u"\u00a0")) + self.failIf(in_table_c12(u"\u00a1")) + + self.failUnless(in_table_c12(u"\u00a0")) + self.failIf(in_table_c12(u"\u00a1")) + + self.failUnless(in_table_c11_c12(u"\u00a0")) + self.failIf(in_table_c11_c12(u"\u00a1")) + + self.failUnless(in_table_c21(u"\u001f")) + self.failIf(in_table_c21(u"\u0020")) + + self.failUnless(in_table_c22(u"\u009f")) + self.failIf(in_table_c22(u"\u00a0")) + + self.failUnless(in_table_c21_c22(u"\u009f")) + self.failIf(in_table_c21_c22(u"\u00a0")) + + self.failUnless(in_table_c3(u"\ue000")) + self.failIf(in_table_c3(u"\uf900")) + + self.failUnless(in_table_c4(u"\uffff")) + self.failIf(in_table_c4(u"\u0000")) + + self.failUnless(in_table_c5(u"\ud800")) + self.failIf(in_table_c5(u"\ud7ff")) + + self.failUnless(in_table_c6(u"\ufff9")) + self.failIf(in_table_c6(u"\ufffe")) + + self.failUnless(in_table_c7(u"\u2ff0")) + self.failIf(in_table_c7(u"\u2ffc")) + + self.failUnless(in_table_c8(u"\u0340")) + self.failIf(in_table_c8(u"\u0342")) + + # C.9 is not in the bmp + # self.failUnless(in_table_c9(u"\U000E0001")) + # self.failIf(in_table_c8(u"\U000E0002")) + + self.failUnless(in_table_d1(u"\u05be")) + self.failIf(in_table_d1(u"\u05bf")) + + self.failUnless(in_table_d2(u"\u0041")) + self.failIf(in_table_d2(u"\u0040")) + + # This would generate a hash of all predicates. However, running + # it is quite expensive, and only serves to detect changes in the + # unicode database. Instead, stringprep.py asserts the version of + # the database. + + # import hashlib + # predicates = [k for k in dir(stringprep) if k.startswith("in_table")] + # predicates.sort() + # for p in predicates: + # f = getattr(stringprep, p) + # # Collect all BMP code points + # data = ["0"] * 0x10000 + # for i in range(0x10000): + # if f(unichr(i)): + # data[i] = "1" + # data = "".join(data) + # h = hashlib.sha1() + # h.update(data) + # print p, h.hexdigest() + +def test_main(): + test_support.run_unittest(StringprepTests) + +if __name__ == '__main__': + test_main() From python-checkins at python.org Fri Apr 6 21:32:34 2007 From: python-checkins at python.org (collin.winter) Date: Fri, 6 Apr 2007 21:32:34 +0200 (CEST) Subject: [Python-checkins] r54705 - python/trunk/Lib/test/test_crypt.py Message-ID: <20070406193234.8C3B51E400A@bag.python.org> Author: collin.winter Date: Fri Apr 6 21:32:32 2007 New Revision: 54705 Modified: python/trunk/Lib/test/test_crypt.py Log: Import cleanup in test_crypt. Modified: python/trunk/Lib/test/test_crypt.py ============================================================================== --- python/trunk/Lib/test/test_crypt.py (original) +++ python/trunk/Lib/test/test_crypt.py Fri Apr 6 21:32:32 2007 @@ -3,7 +3,7 @@ Roger E. Masse """ -from test.test_support import verify, verbose +from test.test_support import verbose import crypt c = crypt.crypt('mypassword', 'ab') From python-checkins at python.org Fri Apr 6 22:00:10 2007 From: python-checkins at python.org (collin.winter) Date: Fri, 6 Apr 2007 22:00:10 +0200 (CEST) Subject: [Python-checkins] r54706 - python/trunk/Lib/test/test_gc.py Message-ID: <20070406200010.55CBE1E400E@bag.python.org> Author: collin.winter Date: Fri Apr 6 22:00:05 2007 New Revision: 54706 Modified: python/trunk/Lib/test/test_gc.py Log: Convert test_gc to use unittest. Modified: python/trunk/Lib/test/test_gc.py ============================================================================== --- python/trunk/Lib/test/test_gc.py (original) +++ python/trunk/Lib/test/test_gc.py Fri Apr 6 22:00:05 2007 @@ -1,391 +1,12 @@ -from test.test_support import verify, verbose, TestFailed, vereq +import unittest +from test.test_support import verbose, run_unittest import sys import gc import weakref -def expect(actual, expected, name): - if actual != expected: - raise TestFailed, "test_%s: actual %r, expected %r" % ( - name, actual, expected) - -def expect_nonzero(actual, name): - if actual == 0: - raise TestFailed, "test_%s: unexpected zero" % name - -def run_test(name, thunk): - if verbose: - print "testing %s..." % name, - thunk() - if verbose: - print "ok" - -def test_list(): - l = [] - l.append(l) - gc.collect() - del l - expect(gc.collect(), 1, "list") - -def test_dict(): - d = {} - d[1] = d - gc.collect() - del d - expect(gc.collect(), 1, "dict") - -def test_tuple(): - # since tuples are immutable we close the loop with a list - l = [] - t = (l,) - l.append(t) - gc.collect() - del t - del l - expect(gc.collect(), 2, "tuple") - -def test_class(): - class A: - pass - A.a = A - gc.collect() - del A - expect_nonzero(gc.collect(), "class") - -def test_newstyleclass(): - class A(object): - pass - gc.collect() - del A - expect_nonzero(gc.collect(), "staticclass") - -def test_instance(): - class A: - pass - a = A() - a.a = a - gc.collect() - del a - expect_nonzero(gc.collect(), "instance") - -def test_newinstance(): - class A(object): - pass - a = A() - a.a = a - gc.collect() - del a - expect_nonzero(gc.collect(), "newinstance") - class B(list): - pass - class C(B, A): - pass - a = C() - a.a = a - gc.collect() - del a - expect_nonzero(gc.collect(), "newinstance(2)") - del B, C - expect_nonzero(gc.collect(), "newinstance(3)") - A.a = A() - del A - expect_nonzero(gc.collect(), "newinstance(4)") - expect(gc.collect(), 0, "newinstance(5)") - -def test_method(): - # Tricky: self.__init__ is a bound method, it references the instance. - class A: - def __init__(self): - self.init = self.__init__ - a = A() - gc.collect() - del a - expect_nonzero(gc.collect(), "method") - -def test_finalizer(): - # A() is uncollectable if it is part of a cycle, make sure it shows up - # in gc.garbage. - class A: - def __del__(self): pass - class B: - pass - a = A() - a.a = a - id_a = id(a) - b = B() - b.b = b - gc.collect() - del a - del b - expect_nonzero(gc.collect(), "finalizer") - for obj in gc.garbage: - if id(obj) == id_a: - del obj.a - break - else: - raise TestFailed, "didn't find obj in garbage (finalizer)" - gc.garbage.remove(obj) - -def test_finalizer_newclass(): - # A() is uncollectable if it is part of a cycle, make sure it shows up - # in gc.garbage. - class A(object): - def __del__(self): pass - class B(object): - pass - a = A() - a.a = a - id_a = id(a) - b = B() - b.b = b - gc.collect() - del a - del b - expect_nonzero(gc.collect(), "finalizer") - for obj in gc.garbage: - if id(obj) == id_a: - del obj.a - break - else: - raise TestFailed, "didn't find obj in garbage (finalizer)" - gc.garbage.remove(obj) - -def test_function(): - # Tricky: f -> d -> f, code should call d.clear() after the exec to - # break the cycle. - d = {} - exec("def f(): pass\n") in d - gc.collect() - del d - expect(gc.collect(), 2, "function") - -def test_frame(): - def f(): - frame = sys._getframe() - gc.collect() - f() - expect(gc.collect(), 1, "frame") - - -def test_saveall(): - # Verify that cyclic garbage like lists show up in gc.garbage if the - # SAVEALL option is enabled. - - # First make sure we don't save away other stuff that just happens to - # be waiting for collection. - gc.collect() - vereq(gc.garbage, []) # if this fails, someone else created immortal trash - - L = [] - L.append(L) - id_L = id(L) - - debug = gc.get_debug() - gc.set_debug(debug | gc.DEBUG_SAVEALL) - del L - gc.collect() - gc.set_debug(debug) - - vereq(len(gc.garbage), 1) - obj = gc.garbage.pop() - vereq(id(obj), id_L) - -def test_del(): - # __del__ methods can trigger collection, make this to happen - thresholds = gc.get_threshold() - gc.enable() - gc.set_threshold(1) - - class A: - def __del__(self): - dir(self) - a = A() - del a - - gc.disable() - gc.set_threshold(*thresholds) - -def test_del_newclass(): - # __del__ methods can trigger collection, make this to happen - thresholds = gc.get_threshold() - gc.enable() - gc.set_threshold(1) - - class A(object): - def __del__(self): - dir(self) - a = A() - del a - - gc.disable() - gc.set_threshold(*thresholds) - -def test_get_count(): - gc.collect() - expect(gc.get_count(), (0, 0, 0), "get_count()") - a = dict() - expect(gc.get_count(), (1, 0, 0), "get_count()") - -def test_collect_generations(): - gc.collect() - a = dict() - gc.collect(0) - expect(gc.get_count(), (0, 1, 0), "collect(0)") - gc.collect(1) - expect(gc.get_count(), (0, 0, 1), "collect(1)") - gc.collect(2) - expect(gc.get_count(), (0, 0, 0), "collect(1)") - -class Ouch: - n = 0 - def __del__(self): - Ouch.n = Ouch.n + 1 - if Ouch.n % 17 == 0: - gc.collect() - -def test_trashcan(): - # "trashcan" is a hack to prevent stack overflow when deallocating - # very deeply nested tuples etc. It works in part by abusing the - # type pointer and refcount fields, and that can yield horrible - # problems when gc tries to traverse the structures. - # If this test fails (as it does in 2.0, 2.1 and 2.2), it will - # most likely die via segfault. - - # Note: In 2.3 the possibility for compiling without cyclic gc was - # removed, and that in turn allows the trashcan mechanism to work - # via much simpler means (e.g., it never abuses the type pointer or - # refcount fields anymore). Since it's much less likely to cause a - # problem now, the various constants in this expensive (we force a lot - # of full collections) test are cut back from the 2.2 version. - gc.enable() - N = 150 - for count in range(2): - t = [] - for i in range(N): - t = [t, Ouch()] - u = [] - for i in range(N): - u = [u, Ouch()] - v = {} - for i in range(N): - v = {1: v, 2: Ouch()} - gc.disable() - -class Boom: - def __getattr__(self, someattribute): - del self.attr - raise AttributeError - -def test_boom(): - a = Boom() - b = Boom() - a.attr = b - b.attr = a - - gc.collect() - garbagelen = len(gc.garbage) - del a, b - # a<->b are in a trash cycle now. Collection will invoke Boom.__getattr__ - # (to see whether a and b have __del__ methods), and __getattr__ deletes - # the internal "attr" attributes as a side effect. That causes the - # trash cycle to get reclaimed via refcounts falling to 0, thus mutating - # the trash graph as a side effect of merely asking whether __del__ - # exists. This used to (before 2.3b1) crash Python. Now __getattr__ - # isn't called. - expect(gc.collect(), 4, "boom") - expect(len(gc.garbage), garbagelen, "boom") - -class Boom2: - def __init__(self): - self.x = 0 - - def __getattr__(self, someattribute): - self.x += 1 - if self.x > 1: - del self.attr - raise AttributeError - -def test_boom2(): - a = Boom2() - b = Boom2() - a.attr = b - b.attr = a - - gc.collect() - garbagelen = len(gc.garbage) - del a, b - # Much like test_boom(), except that __getattr__ doesn't break the - # cycle until the second time gc checks for __del__. As of 2.3b1, - # there isn't a second time, so this simply cleans up the trash cycle. - # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get reclaimed - # this way. - expect(gc.collect(), 4, "boom2") - expect(len(gc.garbage), garbagelen, "boom2") - -# boom__new and boom2_new are exactly like boom and boom2, except use -# new-style classes. - -class Boom_New(object): - def __getattr__(self, someattribute): - del self.attr - raise AttributeError - -def test_boom_new(): - a = Boom_New() - b = Boom_New() - a.attr = b - b.attr = a - - gc.collect() - garbagelen = len(gc.garbage) - del a, b - expect(gc.collect(), 4, "boom_new") - expect(len(gc.garbage), garbagelen, "boom_new") - -class Boom2_New(object): - def __init__(self): - self.x = 0 - - def __getattr__(self, someattribute): - self.x += 1 - if self.x > 1: - del self.attr - raise AttributeError - -def test_boom2_new(): - a = Boom2_New() - b = Boom2_New() - a.attr = b - b.attr = a - - gc.collect() - garbagelen = len(gc.garbage) - del a, b - expect(gc.collect(), 4, "boom2_new") - expect(len(gc.garbage), garbagelen, "boom2_new") - -def test_get_referents(): - alist = [1, 3, 5] - got = gc.get_referents(alist) - got.sort() - expect(got, alist, "get_referents") - - atuple = tuple(alist) - got = gc.get_referents(atuple) - got.sort() - expect(got, alist, "get_referents") - - adict = {1: 3, 5: 7} - expected = [1, 3, 5, 7] - got = gc.get_referents(adict) - got.sort() - expect(got, expected, "get_referents") - - got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0)) - got.sort() - expect(got, [0, 0] + range(5), "get_referents") - - expect(gc.get_referents(1, 'a', 4j), [], "get_referents") - +### Support code +############################################################################### + # Bug 1055820 has several tests of longstanding bugs involving weakrefs and # cyclic gc. @@ -410,217 +31,556 @@ # gc collects it. self.wr = weakref.ref(C1055820(666), it_happened) -def test_bug1055820b(): - # Corresponds to temp2b.py in the bug report. - ouch = [] - def callback(ignored): - ouch[:] = [wr() for wr in WRs] - - Cs = [C1055820(i) for i in range(2)] - WRs = [weakref.ref(c, callback) for c in Cs] - c = None - - gc.collect() - expect(len(ouch), 0, "bug1055820b") - # Make the two instances trash, and collect again. The bug was that - # the callback materialized a strong reference to an instance, but gc - # cleared the instance's dict anyway. - Cs = None - gc.collect() - expect(len(ouch), 2, "bug1055820b") # else the callbacks didn't run - for x in ouch: - # If the callback resurrected one of these guys, the instance - # would be damaged, with an empty __dict__. - expect(x, None, "bug1055820b") - -def test_bug1055820c(): - # Corresponds to temp2c.py in the bug report. This is pretty elaborate. - - c0 = C1055820(0) - # Move c0 into generation 2. - gc.collect() - - c1 = C1055820(1) - c1.keep_c0_alive = c0 - del c0.loop # now only c1 keeps c0 alive - - c2 = C1055820(2) - c2wr = weakref.ref(c2) # no callback! - - ouch = [] - def callback(ignored): - ouch[:] = [c2wr()] - - # The callback gets associated with a wr on an object in generation 2. - c0wr = weakref.ref(c0, callback) - - c0 = c1 = c2 = None - - # What we've set up: c0, c1, and c2 are all trash now. c0 is in - # generation 2. The only thing keeping it alive is that c1 points to it. - # c1 and c2 are in generation 0, and are in self-loops. There's a global - # weakref to c2 (c2wr), but that weakref has no callback. There's also - # a global weakref to c0 (c0wr), and that does have a callback, and that - # callback references c2 via c2wr(). - # - # c0 has a wr with callback, which references c2wr - # ^ - # | - # | Generation 2 above dots - #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . - # | Generation 0 below dots - # | - # | - # ^->c1 ^->c2 has a wr but no callback - # | | | | - # <--v <--v - # - # So this is the nightmare: when generation 0 gets collected, we see that - # c2 has a callback-free weakref, and c1 doesn't even have a weakref. - # Collecting generation 0 doesn't see c0 at all, and c0 is the only object - # that has a weakref with a callback. gc clears c1 and c2. Clearing c1 - # has the side effect of dropping the refcount on c0 to 0, so c0 goes - # away (despite that it's in an older generation) and c0's wr callback - # triggers. That in turn materializes a reference to c2 via c2wr(), but - # c2 gets cleared anyway by gc. - - # We want to let gc happen "naturally", to preserve the distinction - # between generations. - junk = [] - i = 0 - detector = GC_Detector() - while not detector.gc_happened: - i += 1 - if i > 10000: - raise TestFailed("gc didn't happen after 10000 iterations") - expect(len(ouch), 0, "bug1055820c") - junk.append([]) # this will eventually trigger gc - - expect(len(ouch), 1, "bug1055820c") # else the callback wasn't invoked - for x in ouch: - # If the callback resurrected c2, the instance would be damaged, - # with an empty __dict__. - expect(x, None, "bug1055820c") - -def test_bug1055820d(): - # Corresponds to temp2d.py in the bug report. This is very much like - # test_bug1055820c, but uses a __del__ method instead of a weakref - # callback to sneak in a resurrection of cyclic trash. - - ouch = [] - class D(C1055820): - def __del__(self): - ouch[:] = [c2wr()] +### Tests +############################################################################### + +class GCTests(unittest.TestCase): + def test_list(self): + l = [] + l.append(l) + gc.collect() + del l + self.assertEqual(gc.collect(), 1) + + def test_dict(self): + d = {} + d[1] = d + gc.collect() + del d + self.assertEqual(gc.collect(), 1) + + def test_tuple(self): + # since tuples are immutable we close the loop with a list + l = [] + t = (l,) + l.append(t) + gc.collect() + del t + del l + self.assertEqual(gc.collect(), 2) + + def test_class(self): + class A: + pass + A.a = A + gc.collect() + del A + self.assertNotEqual(gc.collect(), 0) + + def test_newstyleclass(self): + class A(object): + pass + gc.collect() + del A + self.assertNotEqual(gc.collect(), 0) + + def test_instance(self): + class A: + pass + a = A() + a.a = a + gc.collect() + del a + self.assertNotEqual(gc.collect(), 0) + + def test_newinstance(self): + class A(object): + pass + a = A() + a.a = a + gc.collect() + del a + self.assertNotEqual(gc.collect(), 0) + class B(list): + pass + class C(B, A): + pass + a = C() + a.a = a + gc.collect() + del a + self.assertNotEqual(gc.collect(), 0) + del B, C + self.assertNotEqual(gc.collect(), 0) + A.a = A() + del A + self.assertNotEqual(gc.collect(), 0) + self.assertEqual(gc.collect(), 0) + + def test_method(self): + # Tricky: self.__init__ is a bound method, it references the instance. + class A: + def __init__(self): + self.init = self.__init__ + a = A() + gc.collect() + del a + self.assertNotEqual(gc.collect(), 0) + + def test_finalizer(self): + # A() is uncollectable if it is part of a cycle, make sure it shows up + # in gc.garbage. + class A: + def __del__(self): pass + class B: + pass + a = A() + a.a = a + id_a = id(a) + b = B() + b.b = b + gc.collect() + del a + del b + self.assertNotEqual(gc.collect(), 0) + for obj in gc.garbage: + if id(obj) == id_a: + del obj.a + break + else: + self.fail("didn't find obj in garbage (finalizer)") + gc.garbage.remove(obj) + + def test_finalizer_newclass(self): + # A() is uncollectable if it is part of a cycle, make sure it shows up + # in gc.garbage. + class A(object): + def __del__(self): pass + class B(object): + pass + a = A() + a.a = a + id_a = id(a) + b = B() + b.b = b + gc.collect() + del a + del b + self.assertNotEqual(gc.collect(), 0) + for obj in gc.garbage: + if id(obj) == id_a: + del obj.a + break + else: + self.fail("didn't find obj in garbage (finalizer)") + gc.garbage.remove(obj) + + def test_function(self): + # Tricky: f -> d -> f, code should call d.clear() after the exec to + # break the cycle. + d = {} + exec("def f(): pass\n") in d + gc.collect() + del d + self.assertEqual(gc.collect(), 2) + + def test_frame(self): + def f(): + frame = sys._getframe() + gc.collect() + f() + self.assertEqual(gc.collect(), 1) + + def test_saveall(self): + # Verify that cyclic garbage like lists show up in gc.garbage if the + # SAVEALL option is enabled. + + # First make sure we don't save away other stuff that just happens to + # be waiting for collection. + gc.collect() + # if this fails, someone else created immortal trash + self.assertEqual(gc.garbage, []) + + L = [] + L.append(L) + id_L = id(L) + + debug = gc.get_debug() + gc.set_debug(debug | gc.DEBUG_SAVEALL) + del L + gc.collect() + gc.set_debug(debug) - d0 = D(0) - # Move all the above into generation 2. - gc.collect() - - c1 = C1055820(1) - c1.keep_d0_alive = d0 - del d0.loop # now only c1 keeps d0 alive - - c2 = C1055820(2) - c2wr = weakref.ref(c2) # no callback! - - d0 = c1 = c2 = None - - # What we've set up: d0, c1, and c2 are all trash now. d0 is in - # generation 2. The only thing keeping it alive is that c1 points to it. - # c1 and c2 are in generation 0, and are in self-loops. There's a global - # weakref to c2 (c2wr), but that weakref has no callback. There are no - # other weakrefs. - # - # d0 has a __del__ method that references c2wr - # ^ - # | - # | Generation 2 above dots - #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . - # | Generation 0 below dots - # | - # | - # ^->c1 ^->c2 has a wr but no callback - # | | | | - # <--v <--v - # - # So this is the nightmare: when generation 0 gets collected, we see that - # c2 has a callback-free weakref, and c1 doesn't even have a weakref. - # Collecting generation 0 doesn't see d0 at all. gc clears c1 and c2. - # Clearing c1 has the side effect of dropping the refcount on d0 to 0, so - # d0 goes away (despite that it's in an older generation) and d0's __del__ - # triggers. That in turn materializes a reference to c2 via c2wr(), but - # c2 gets cleared anyway by gc. - - # We want to let gc happen "naturally", to preserve the distinction - # between generations. - detector = GC_Detector() - junk = [] - i = 0 - while not detector.gc_happened: - i += 1 - if i > 10000: - raise TestFailed("gc didn't happen after 10000 iterations") - expect(len(ouch), 0, "bug1055820d") - junk.append([]) # this will eventually trigger gc - - expect(len(ouch), 1, "bug1055820d") # else __del__ wasn't invoked - for x in ouch: - # If __del__ resurrected c2, the instance would be damaged, with an - # empty __dict__. - expect(x, None, "bug1055820d") - - -def test_all(): - gc.collect() # Delete 2nd generation garbage - run_test("lists", test_list) - run_test("dicts", test_dict) - run_test("tuples", test_tuple) - run_test("classes", test_class) - run_test("new style classes", test_newstyleclass) - run_test("instances", test_instance) - run_test("new instances", test_newinstance) - run_test("methods", test_method) - run_test("functions", test_function) - run_test("frames", test_frame) - run_test("finalizers", test_finalizer) - run_test("finalizers (new class)", test_finalizer_newclass) - run_test("__del__", test_del) - run_test("__del__ (new class)", test_del_newclass) - run_test("get_count()", test_get_count) - run_test("collect(n)", test_collect_generations) - run_test("saveall", test_saveall) - run_test("trashcan", test_trashcan) - run_test("boom", test_boom) - run_test("boom2", test_boom2) - run_test("boom_new", test_boom_new) - run_test("boom2_new", test_boom2_new) - run_test("get_referents", test_get_referents) - run_test("bug1055820b", test_bug1055820b) + self.assertEqual(len(gc.garbage), 1) + obj = gc.garbage.pop() + self.assertEqual(id(obj), id_L) + + def test_del(self): + # __del__ methods can trigger collection, make this to happen + thresholds = gc.get_threshold() + gc.enable() + gc.set_threshold(1) + + class A: + def __del__(self): + dir(self) + a = A() + del a - gc.enable() - try: - run_test("bug1055820c", test_bug1055820c) - finally: gc.disable() + gc.set_threshold(*thresholds) - gc.enable() - try: - run_test("bug1055820d", test_bug1055820d) - finally: + def test_del_newclass(self): + # __del__ methods can trigger collection, make this to happen + thresholds = gc.get_threshold() + gc.enable() + gc.set_threshold(1) + + class A(object): + def __del__(self): + dir(self) + a = A() + del a + + gc.disable() + gc.set_threshold(*thresholds) + + def test_get_count(self): + gc.collect() + self.assertEqual(gc.get_count(), (0, 0, 0)) + a = dict() + self.assertEqual(gc.get_count(), (1, 0, 0)) + + def test_collect_generations(self): + gc.collect() + a = dict() + gc.collect(0) + self.assertEqual(gc.get_count(), (0, 1, 0)) + gc.collect(1) + self.assertEqual(gc.get_count(), (0, 0, 1)) + gc.collect(2) + self.assertEqual(gc.get_count(), (0, 0, 0)) + + def test_trashcan(self): + class Ouch: + n = 0 + def __del__(self): + Ouch.n = Ouch.n + 1 + if Ouch.n % 17 == 0: + gc.collect() + + # "trashcan" is a hack to prevent stack overflow when deallocating + # very deeply nested tuples etc. It works in part by abusing the + # type pointer and refcount fields, and that can yield horrible + # problems when gc tries to traverse the structures. + # If this test fails (as it does in 2.0, 2.1 and 2.2), it will + # most likely die via segfault. + + # Note: In 2.3 the possibility for compiling without cyclic gc was + # removed, and that in turn allows the trashcan mechanism to work + # via much simpler means (e.g., it never abuses the type pointer or + # refcount fields anymore). Since it's much less likely to cause a + # problem now, the various constants in this expensive (we force a lot + # of full collections) test are cut back from the 2.2 version. + gc.enable() + N = 150 + for count in range(2): + t = [] + for i in range(N): + t = [t, Ouch()] + u = [] + for i in range(N): + u = [u, Ouch()] + v = {} + for i in range(N): + v = {1: v, 2: Ouch()} + gc.disable() + + def test_boom(self): + class Boom: + def __getattr__(self, someattribute): + del self.attr + raise AttributeError + + a = Boom() + b = Boom() + a.attr = b + b.attr = a + + gc.collect() + garbagelen = len(gc.garbage) + del a, b + # a<->b are in a trash cycle now. Collection will invoke + # Boom.__getattr__ (to see whether a and b have __del__ methods), and + # __getattr__ deletes the internal "attr" attributes as a side effect. + # That causes the trash cycle to get reclaimed via refcounts falling to + # 0, thus mutating the trash graph as a side effect of merely asking + # whether __del__ exists. This used to (before 2.3b1) crash Python. + # Now __getattr__ isn't called. + self.assertEqual(gc.collect(), 4) + self.assertEqual(len(gc.garbage), garbagelen) + + def test_boom2(self): + class Boom2: + def __init__(self): + self.x = 0 + + def __getattr__(self, someattribute): + self.x += 1 + if self.x > 1: + del self.attr + raise AttributeError + + a = Boom2() + b = Boom2() + a.attr = b + b.attr = a + + gc.collect() + garbagelen = len(gc.garbage) + del a, b + # Much like test_boom(), except that __getattr__ doesn't break the + # cycle until the second time gc checks for __del__. As of 2.3b1, + # there isn't a second time, so this simply cleans up the trash cycle. + # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get + # reclaimed this way. + self.assertEqual(gc.collect(), 4) + self.assertEqual(len(gc.garbage), garbagelen) + + def test_boom_new(self): + # boom__new and boom2_new are exactly like boom and boom2, except use + # new-style classes. + + class Boom_New(object): + def __getattr__(self, someattribute): + del self.attr + raise AttributeError + + a = Boom_New() + b = Boom_New() + a.attr = b + b.attr = a + + gc.collect() + garbagelen = len(gc.garbage) + del a, b + self.assertEqual(gc.collect(), 4) + self.assertEqual(len(gc.garbage), garbagelen) + + def test_boom2_new(self): + class Boom2_New(object): + def __init__(self): + self.x = 0 + + def __getattr__(self, someattribute): + self.x += 1 + if self.x > 1: + del self.attr + raise AttributeError + + a = Boom2_New() + b = Boom2_New() + a.attr = b + b.attr = a + + gc.collect() + garbagelen = len(gc.garbage) + del a, b + self.assertEqual(gc.collect(), 4) + self.assertEqual(len(gc.garbage), garbagelen) + + def test_get_referents(self): + alist = [1, 3, 5] + got = gc.get_referents(alist) + got.sort() + self.assertEqual(got, alist) + + atuple = tuple(alist) + got = gc.get_referents(atuple) + got.sort() + self.assertEqual(got, alist) + + adict = {1: 3, 5: 7} + expected = [1, 3, 5, 7] + got = gc.get_referents(adict) + got.sort() + self.assertEqual(got, expected) + + got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0)) + got.sort() + self.assertEqual(got, [0, 0] + range(5)) + + self.assertEqual(gc.get_referents(1, 'a', 4j), []) + + def test_bug1055820b(self): + # Corresponds to temp2b.py in the bug report. + + ouch = [] + def callback(ignored): + ouch[:] = [wr() for wr in WRs] + + Cs = [C1055820(i) for i in range(2)] + WRs = [weakref.ref(c, callback) for c in Cs] + c = None + + gc.collect() + self.assertEqual(len(ouch), 0) + # Make the two instances trash, and collect again. The bug was that + # the callback materialized a strong reference to an instance, but gc + # cleared the instance's dict anyway. + Cs = None + gc.collect() + self.assertEqual(len(ouch), 2) # else the callbacks didn't run + for x in ouch: + # If the callback resurrected one of these guys, the instance + # would be damaged, with an empty __dict__. + self.assertEqual(x, None) + +class GCTogglingTests(unittest.TestCase): + def setUp(self): + gc.enable() + + def tearDown(self): gc.disable() + + def test_bug1055820c(self): + # Corresponds to temp2c.py in the bug report. This is pretty + # elaborate. + + c0 = C1055820(0) + # Move c0 into generation 2. + gc.collect() + + c1 = C1055820(1) + c1.keep_c0_alive = c0 + del c0.loop # now only c1 keeps c0 alive + + c2 = C1055820(2) + c2wr = weakref.ref(c2) # no callback! + + ouch = [] + def callback(ignored): + ouch[:] = [c2wr()] -def test(): - if verbose: - print "disabling automatic collection" + # The callback gets associated with a wr on an object in generation 2. + c0wr = weakref.ref(c0, callback) + + c0 = c1 = c2 = None + + # What we've set up: c0, c1, and c2 are all trash now. c0 is in + # generation 2. The only thing keeping it alive is that c1 points to + # it. c1 and c2 are in generation 0, and are in self-loops. There's a + # global weakref to c2 (c2wr), but that weakref has no callback. + # There's also a global weakref to c0 (c0wr), and that does have a + # callback, and that callback references c2 via c2wr(). + # + # c0 has a wr with callback, which references c2wr + # ^ + # | + # | Generation 2 above dots + #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . + # | Generation 0 below dots + # | + # | + # ^->c1 ^->c2 has a wr but no callback + # | | | | + # <--v <--v + # + # So this is the nightmare: when generation 0 gets collected, we see + # that c2 has a callback-free weakref, and c1 doesn't even have a + # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is + # the only object that has a weakref with a callback. gc clears c1 + # and c2. Clearing c1 has the side effect of dropping the refcount on + # c0 to 0, so c0 goes away (despite that it's in an older generation) + # and c0's wr callback triggers. That in turn materializes a reference + # to c2 via c2wr(), but c2 gets cleared anyway by gc. + + # We want to let gc happen "naturally", to preserve the distinction + # between generations. + junk = [] + i = 0 + detector = GC_Detector() + while not detector.gc_happened: + i += 1 + if i > 10000: + self.fail("gc didn't happen after 10000 iterations") + self.assertEqual(len(ouch), 0) + junk.append([]) # this will eventually trigger gc + + self.assertEqual(len(ouch), 1) # else the callback wasn't invoked + for x in ouch: + # If the callback resurrected c2, the instance would be damaged, + # with an empty __dict__. + self.assertEqual(x, None) + + def test_bug1055820d(self): + # Corresponds to temp2d.py in the bug report. This is very much like + # test_bug1055820c, but uses a __del__ method instead of a weakref + # callback to sneak in a resurrection of cyclic trash. + + ouch = [] + class D(C1055820): + def __del__(self): + ouch[:] = [c2wr()] + + d0 = D(0) + # Move all the above into generation 2. + gc.collect() + + c1 = C1055820(1) + c1.keep_d0_alive = d0 + del d0.loop # now only c1 keeps d0 alive + + c2 = C1055820(2) + c2wr = weakref.ref(c2) # no callback! + + d0 = c1 = c2 = None + + # What we've set up: d0, c1, and c2 are all trash now. d0 is in + # generation 2. The only thing keeping it alive is that c1 points to + # it. c1 and c2 are in generation 0, and are in self-loops. There's + # a global weakref to c2 (c2wr), but that weakref has no callback. + # There are no other weakrefs. + # + # d0 has a __del__ method that references c2wr + # ^ + # | + # | Generation 2 above dots + #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . + # | Generation 0 below dots + # | + # | + # ^->c1 ^->c2 has a wr but no callback + # | | | | + # <--v <--v + # + # So this is the nightmare: when generation 0 gets collected, we see + # that c2 has a callback-free weakref, and c1 doesn't even have a + # weakref. Collecting generation 0 doesn't see d0 at all. gc clears + # c1 and c2. Clearing c1 has the side effect of dropping the refcount + # on d0 to 0, so d0 goes away (despite that it's in an older + # generation) and d0's __del__ triggers. That in turn materializes + # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc. + + # We want to let gc happen "naturally", to preserve the distinction + # between generations. + detector = GC_Detector() + junk = [] + i = 0 + while not detector.gc_happened: + i += 1 + if i > 10000: + self.fail("gc didn't happen after 10000 iterations") + self.assertEqual(len(ouch), 0) + junk.append([]) # this will eventually trigger gc + + self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked + for x in ouch: + # If __del__ resurrected c2, the instance would be damaged, with an + # empty __dict__. + self.assertEqual(x, None) + +def test_main(): enabled = gc.isenabled() gc.disable() - verify(not gc.isenabled()) + assert not gc.isenabled() debug = gc.get_debug() gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak try: - test_all() + gc.collect() # Delete 2nd generation garbage + run_unittest(GCTests, GCTogglingTests) finally: gc.set_debug(debug) # test gc.enable() even if GC is disabled by default @@ -628,9 +588,9 @@ print "restoring automatic collection" # make sure to always test gc.enable() gc.enable() - verify(gc.isenabled()) + assert gc.isenabled() if not enabled: gc.disable() - - -test() + +if __name__ == "__main__": + test_main() From python-checkins at python.org Fri Apr 6 22:03:11 2007 From: python-checkins at python.org (collin.winter) Date: Fri, 6 Apr 2007 22:03:11 +0200 (CEST) Subject: [Python-checkins] r54707 - python/trunk/Lib/test/test_module.py Message-ID: <20070406200311.F318B1E400A@bag.python.org> Author: collin.winter Date: Fri Apr 6 22:03:11 2007 New Revision: 54707 Modified: python/trunk/Lib/test/test_module.py Log: Convert test_module to use unittest. Modified: python/trunk/Lib/test/test_module.py ============================================================================== --- python/trunk/Lib/test/test_module.py (original) +++ python/trunk/Lib/test/test_module.py Fri Apr 6 22:03:11 2007 @@ -1,48 +1,61 @@ # Test the module type - -from test.test_support import verify, vereq, verbose, TestFailed +import unittest +from test.test_support import verbose, run_unittest import sys -module = type(sys) - -# An uninitialized module has no __dict__ or __name__, and __doc__ is None -foo = module.__new__(module) -verify(foo.__dict__ is None) -try: - s = foo.__name__ -except AttributeError: - pass -else: - raise TestFailed, "__name__ = %s" % repr(s) -vereq(foo.__doc__, module.__doc__) - -# Regularly initialized module, no docstring -foo = module("foo") -vereq(foo.__name__, "foo") -vereq(foo.__doc__, None) -vereq(foo.__dict__, {"__name__": "foo", "__doc__": None}) - -# ASCII docstring -foo = module("foo", "foodoc") -vereq(foo.__name__, "foo") -vereq(foo.__doc__, "foodoc") -vereq(foo.__dict__, {"__name__": "foo", "__doc__": "foodoc"}) - -# Unicode docstring -foo = module("foo", u"foodoc\u1234") -vereq(foo.__name__, "foo") -vereq(foo.__doc__, u"foodoc\u1234") -vereq(foo.__dict__, {"__name__": "foo", "__doc__": u"foodoc\u1234"}) - -# Reinitialization should not replace the __dict__ -foo.bar = 42 -d = foo.__dict__ -foo.__init__("foo", "foodoc") -vereq(foo.__name__, "foo") -vereq(foo.__doc__, "foodoc") -vereq(foo.bar, 42) -vereq(foo.__dict__, {"__name__": "foo", "__doc__": "foodoc", "bar": 42}) -verify(foo.__dict__ is d) +ModuleType = type(sys) -if verbose: - print "All OK" +class ModuleTests(unittest.TestCase): + def test_uninitialized(self): + # An uninitialized module has no __dict__ or __name__, + # and __doc__ is None + foo = ModuleType.__new__(ModuleType) + self.failUnless(foo.__dict__ is None) + try: + s = foo.__name__ + self.fail("__name__ = %s" % repr(s)) + except AttributeError: + pass + self.assertEqual(foo.__doc__, ModuleType.__doc__) + + def test_no_docstring(self): + # Regularly initialized module, no docstring + foo = ModuleType("foo") + self.assertEqual(foo.__name__, "foo") + self.assertEqual(foo.__doc__, None) + self.assertEqual(foo.__dict__, {"__name__": "foo", "__doc__": None}) + + def test_ascii_docstring(self): + # ASCII docstring + foo = ModuleType("foo", "foodoc") + self.assertEqual(foo.__name__, "foo") + self.assertEqual(foo.__doc__, "foodoc") + self.assertEqual(foo.__dict__, + {"__name__": "foo", "__doc__": "foodoc"}) + + def test_unicode_docstring(self): + # Unicode docstring + foo = ModuleType("foo", u"foodoc\u1234") + self.assertEqual(foo.__name__, "foo") + self.assertEqual(foo.__doc__, u"foodoc\u1234") + self.assertEqual(foo.__dict__, + {"__name__": "foo", "__doc__": u"foodoc\u1234"}) + + def test_reinit(self): + # Reinitialization should not replace the __dict__ + foo = ModuleType("foo", u"foodoc\u1234") + foo.bar = 42 + d = foo.__dict__ + foo.__init__("foo", "foodoc") + self.assertEqual(foo.__name__, "foo") + self.assertEqual(foo.__doc__, "foodoc") + self.assertEqual(foo.bar, 42) + self.assertEqual(foo.__dict__, + {"__name__": "foo", "__doc__": "foodoc", "bar": 42}) + self.failUnless(foo.__dict__ is d) + +def test_main(): + run_unittest(ModuleTests) + +if __name__ == '__main__': + test_main() From nnorwitz at gmail.com Fri Apr 6 22:15:52 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Fri, 6 Apr 2007 16:15:52 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070406201552.GA8517@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [480169 refs] From python-checkins at python.org Sat Apr 7 06:40:44 2007 From: python-checkins at python.org (collin.winter) Date: Sat, 7 Apr 2007 06:40:44 +0200 (CEST) Subject: [Python-checkins] r54711 - python/trunk/Lib/test/test_fileinput.py Message-ID: <20070407044044.1153F1E4006@bag.python.org> Author: collin.winter Date: Sat Apr 7 06:40:43 2007 New Revision: 54711 Modified: python/trunk/Lib/test/test_fileinput.py Log: Convert test_fileinput to use unittest. Modified: python/trunk/Lib/test/test_fileinput.py ============================================================================== --- python/trunk/Lib/test/test_fileinput.py (original) +++ python/trunk/Lib/test/test_fileinput.py Sat Apr 7 06:40:43 2007 @@ -3,7 +3,9 @@ Nick Mathewson ''' -from test.test_support import verify, verbose, TESTFN, TestFailed +import unittest +from test.test_support import verbose, TESTFN, run_unittest +from test.test_support import unlink as safe_unlink import sys, os, re from StringIO import StringIO from fileinput import FileInput, hook_encoded @@ -22,206 +24,202 @@ f.close() return name -pat = re.compile(r'LINE (\d+) OF FILE (\d+)') - def remove_tempfiles(*names): for name in names: - try: - os.unlink(name) - except: - pass - -def runTests(t1, t2, t3, t4, bs=0, round=0): - start = 1 + round*6 - if verbose: - print '%s. Simple iteration (bs=%s)' % (start+0, bs) - fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) - lines = list(fi) - fi.close() - verify(len(lines) == 31) - verify(lines[4] == 'Line 5 of file 1\n') - verify(lines[30] == 'Line 1 of file 4\n') - verify(fi.lineno() == 31) - verify(fi.filename() == t4) - - if verbose: - print '%s. Status variables (bs=%s)' % (start+1, bs) - fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) - s = "x" - while s and s != 'Line 6 of file 2\n': - s = fi.readline() - verify(fi.filename() == t2) - verify(fi.lineno() == 21) - verify(fi.filelineno() == 6) - verify(not fi.isfirstline()) - verify(not fi.isstdin()) - - if verbose: - print '%s. Nextfile (bs=%s)' % (start+2, bs) - fi.nextfile() - verify(fi.readline() == 'Line 1 of file 3\n') - verify(fi.lineno() == 22) - fi.close() - - if verbose: - print '%s. Stdin (bs=%s)' % (start+3, bs) - fi = FileInput(files=(t1, t2, t3, t4, '-'), bufsize=bs) - savestdin = sys.stdin - try: - sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n") + safe_unlink(name) + +class BufferSizesTests(unittest.TestCase): + def test_buffer_sizes(self): + # First, run the tests with default and teeny buffer size. + for round, bs in (0, 0), (1, 30): + try: + t1 = writeTmp(1, ["Line %s of file 1\n" % (i+1) for i in range(15)]) + t2 = writeTmp(2, ["Line %s of file 2\n" % (i+1) for i in range(10)]) + t3 = writeTmp(3, ["Line %s of file 3\n" % (i+1) for i in range(5)]) + t4 = writeTmp(4, ["Line %s of file 4\n" % (i+1) for i in range(1)]) + self.buffer_size_test(t1, t2, t3, t4, bs, round) + finally: + remove_tempfiles(t1, t2, t3, t4) + + def buffer_size_test(self, t1, t2, t3, t4, bs=0, round=0): + pat = re.compile(r'LINE (\d+) OF FILE (\d+)') + + start = 1 + round*6 + if verbose: + print '%s. Simple iteration (bs=%s)' % (start+0, bs) + fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) lines = list(fi) - verify(len(lines) == 33) - verify(lines[32] == 'Line 2 of stdin\n') - verify(fi.filename() == '') + fi.close() + self.assertEqual(len(lines), 31) + self.assertEqual(lines[4], 'Line 5 of file 1\n') + self.assertEqual(lines[30], 'Line 1 of file 4\n') + self.assertEqual(fi.lineno(), 31) + self.assertEqual(fi.filename(), t4) + + if verbose: + print '%s. Status variables (bs=%s)' % (start+1, bs) + fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) + s = "x" + while s and s != 'Line 6 of file 2\n': + s = fi.readline() + self.assertEqual(fi.filename(), t2) + self.assertEqual(fi.lineno(), 21) + self.assertEqual(fi.filelineno(), 6) + self.failIf(fi.isfirstline()) + self.failIf(fi.isstdin()) + + if verbose: + print '%s. Nextfile (bs=%s)' % (start+2, bs) + fi.nextfile() + self.assertEqual(fi.readline(), 'Line 1 of file 3\n') + self.assertEqual(fi.lineno(), 22) + fi.close() + + if verbose: + print '%s. Stdin (bs=%s)' % (start+3, bs) + fi = FileInput(files=(t1, t2, t3, t4, '-'), bufsize=bs) + savestdin = sys.stdin + try: + sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n") + lines = list(fi) + self.assertEqual(len(lines), 33) + self.assertEqual(lines[32], 'Line 2 of stdin\n') + self.assertEqual(fi.filename(), '') + fi.nextfile() + finally: + sys.stdin = savestdin + + if verbose: + print '%s. Boundary conditions (bs=%s)' % (start+4, bs) + fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) + self.assertEqual(fi.lineno(), 0) + self.assertEqual(fi.filename(), None) fi.nextfile() - finally: - sys.stdin = savestdin + self.assertEqual(fi.lineno(), 0) + self.assertEqual(fi.filename(), None) - if verbose: - print '%s. Boundary conditions (bs=%s)' % (start+4, bs) - fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) - verify(fi.lineno() == 0) - verify(fi.filename() == None) - fi.nextfile() - verify(fi.lineno() == 0) - verify(fi.filename() == None) - - if verbose: - print '%s. Inplace (bs=%s)' % (start+5, bs) - savestdout = sys.stdout - try: - fi = FileInput(files=(t1, t2, t3, t4), inplace=1, bufsize=bs) + if verbose: + print '%s. Inplace (bs=%s)' % (start+5, bs) + savestdout = sys.stdout + try: + fi = FileInput(files=(t1, t2, t3, t4), inplace=1, bufsize=bs) + for line in fi: + line = line[:-1].upper() + print line + fi.close() + finally: + sys.stdout = savestdout + + fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) for line in fi: - line = line[:-1].upper() - print line + self.assertEqual(line[-1], '\n') + m = pat.match(line[:-1]) + self.assertNotEqual(m, None) + self.assertEqual(int(m.group(1)), fi.filelineno()) fi.close() - finally: - sys.stdout = savestdout + +class FileInputTests(unittest.TestCase): + def test_zero_byte_files(self): + try: + t1 = writeTmp(1, [""]) + t2 = writeTmp(2, [""]) + t3 = writeTmp(3, ["The only line there is.\n"]) + t4 = writeTmp(4, [""]) + fi = FileInput(files=(t1, t2, t3, t4)) + + line = fi.readline() + self.assertEqual(line, 'The only line there is.\n') + self.assertEqual(fi.lineno(), 1) + self.assertEqual(fi.filelineno(), 1) + self.assertEqual(fi.filename(), t3) + + line = fi.readline() + self.failIf(line) + self.assertEqual(fi.lineno(), 1) + self.assertEqual(fi.filelineno(), 0) + self.assertEqual(fi.filename(), t4) + fi.close() + finally: + remove_tempfiles(t1, t2, t3, t4) + + def test_files_that_dont_end_with_newline(self): + try: + t1 = writeTmp(1, ["A\nB\nC"]) + t2 = writeTmp(2, ["D\nE\nF"]) + fi = FileInput(files=(t1, t2)) + lines = list(fi) + self.assertEqual(lines, ["A\n", "B\n", "C", "D\n", "E\n", "F"]) + self.assertEqual(fi.filelineno(), 3) + self.assertEqual(fi.lineno(), 6) + finally: + remove_tempfiles(t1, t2) + + def test_unicode_filenames(self): + try: + t1 = writeTmp(1, ["A\nB"]) + encoding = sys.getfilesystemencoding() + if encoding is None: + encoding = 'ascii' + fi = FileInput(files=unicode(t1, encoding)) + lines = list(fi) + self.assertEqual(lines, ["A\n", "B"]) + finally: + remove_tempfiles(t1) + + def test_fileno(self): + try: + t1 = writeTmp(1, ["A\nB"]) + t2 = writeTmp(2, ["C\nD"]) + fi = FileInput(files=(t1, t2)) + self.assertEqual(fi.fileno(), -1) + line = fi.next() + self.assertNotEqual(fi.fileno(), -1) + fi.nextfile() + self.assertEqual(fi.fileno(), -1) + line = list(fi) + self.assertEqual(fi.fileno(), -1) + finally: + remove_tempfiles(t1, t2) + + def test_opening_mode(self): + try: + # invalid mode, should raise ValueError + fi = FileInput(mode="w") + self.fail("FileInput should reject invalid mode argument") + except ValueError: + pass + try: + # try opening in universal newline mode + t1 = writeTmp(1, ["A\nB\r\nC\rD"], mode="wb") + fi = FileInput(files=t1, mode="U") + lines = list(fi) + self.assertEqual(lines, ["A\n", "B\n", "C\n", "D"]) + finally: + remove_tempfiles(t1) - fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) - for line in fi: - verify(line[-1] == '\n') - m = pat.match(line[:-1]) - verify(m != None) - verify(int(m.group(1)) == fi.filelineno()) - fi.close() - - -def writeFiles(): - global t1, t2, t3, t4 - t1 = writeTmp(1, ["Line %s of file 1\n" % (i+1) for i in range(15)]) - t2 = writeTmp(2, ["Line %s of file 2\n" % (i+1) for i in range(10)]) - t3 = writeTmp(3, ["Line %s of file 3\n" % (i+1) for i in range(5)]) - t4 = writeTmp(4, ["Line %s of file 4\n" % (i+1) for i in range(1)]) - -# First, run the tests with default and teeny buffer size. -for round, bs in (0, 0), (1, 30): - try: - writeFiles() - runTests(t1, t2, t3, t4, bs, round) - finally: - remove_tempfiles(t1, t2, t3, t4) - -# Next, check for proper behavior with 0-byte files. -if verbose: - print "13. 0-byte files" -try: - t1 = writeTmp(1, [""]) - t2 = writeTmp(2, [""]) - t3 = writeTmp(3, ["The only line there is.\n"]) - t4 = writeTmp(4, [""]) - fi = FileInput(files=(t1, t2, t3, t4)) - line = fi.readline() - verify(line == 'The only line there is.\n') - verify(fi.lineno() == 1) - verify(fi.filelineno() == 1) - verify(fi.filename() == t3) - line = fi.readline() - verify(not line) - verify(fi.lineno() == 1) - verify(fi.filelineno() == 0) - verify(fi.filename() == t4) - fi.close() -finally: - remove_tempfiles(t1, t2, t3, t4) - -if verbose: - print "14. Files that don't end with newline" -try: - t1 = writeTmp(1, ["A\nB\nC"]) - t2 = writeTmp(2, ["D\nE\nF"]) - fi = FileInput(files=(t1, t2)) - lines = list(fi) - verify(lines == ["A\n", "B\n", "C", "D\n", "E\n", "F"]) - verify(fi.filelineno() == 3) - verify(fi.lineno() == 6) -finally: - remove_tempfiles(t1, t2) - -if verbose: - print "15. Unicode filenames" -try: - t1 = writeTmp(1, ["A\nB"]) - encoding = sys.getfilesystemencoding() - if encoding is None: - encoding = 'ascii' - fi = FileInput(files=unicode(t1, encoding)) - lines = list(fi) - verify(lines == ["A\n", "B"]) -finally: - remove_tempfiles(t1) - -if verbose: - print "16. fileno()" -try: - t1 = writeTmp(1, ["A\nB"]) - t2 = writeTmp(2, ["C\nD"]) - fi = FileInput(files=(t1, t2)) - verify(fi.fileno() == -1) - line = fi.next() - verify(fi.fileno() != -1) - fi.nextfile() - verify(fi.fileno() == -1) - line = list(fi) - verify(fi.fileno() == -1) -finally: - remove_tempfiles(t1, t2) - -if verbose: - print "17. Specify opening mode" -try: - # invalid mode, should raise ValueError - fi = FileInput(mode="w") - raise TestFailed("FileInput should reject invalid mode argument") -except ValueError: - pass -try: - # try opening in universal newline mode - t1 = writeTmp(1, ["A\nB\r\nC\rD"], mode="wb") - fi = FileInput(files=t1, mode="U") - lines = list(fi) - verify(lines == ["A\n", "B\n", "C\n", "D"]) -finally: - remove_tempfiles(t1) - -if verbose: - print "18. Test file opening hook" -try: - # cannot use openhook and inplace mode - fi = FileInput(inplace=1, openhook=lambda f,m: None) - raise TestFailed("FileInput should raise if both inplace " - "and openhook arguments are given") -except ValueError: - pass -try: - fi = FileInput(openhook=1) - raise TestFailed("FileInput should check openhook for being callable") -except ValueError: - pass -try: - t1 = writeTmp(1, ["A\nB"], mode="wb") - fi = FileInput(files=t1, openhook=hook_encoded("rot13")) - lines = list(fi) - verify(lines == ["N\n", "O"]) -finally: - remove_tempfiles(t1) + def test_file_opening_hook(self): + try: + # cannot use openhook and inplace mode + fi = FileInput(inplace=1, openhook=lambda f,m: None) + self.fail("FileInput should raise if both inplace " + "and openhook arguments are given") + except ValueError: + pass + try: + fi = FileInput(openhook=1) + self.fail("FileInput should check openhook for being callable") + except ValueError: + pass + try: + t1 = writeTmp(1, ["A\nB"], mode="wb") + fi = FileInput(files=t1, openhook=hook_encoded("rot13")) + lines = list(fi) + self.assertEqual(lines, ["N\n", "O"]) + finally: + remove_tempfiles(t1) + +def test_main(): + run_unittest(BufferSizesTests, FileInputTests) + +if __name__ == "__main__": + test_main() From nnorwitz at gmail.com Sat Apr 7 10:13:44 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sat, 7 Apr 2007 04:13:44 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070407081344.GA15773@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [482130 refs] From glenn.rossie at pandora.be Sat Apr 7 21:25:43 2007 From: glenn.rossie at pandora.be (izzy green) Date: Sat, 7 Apr 2007 20:25:43 +0100 Subject: [Python-checkins] Cheap Codeine Tylenol3 Online - USA Pharmacy Message-ID: <000501c7794a$88d0e200$ec725351@izzything> please can you help me?how do i order?my name is glenn and i live in belgium -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/python-checkins/attachments/20070407/def399d8/attachment.htm From nnorwitz at gmail.com Sat Apr 7 22:13:37 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sat, 7 Apr 2007 16:13:37 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070407201337.GA12230@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [482122 refs] From python-checkins at python.org Sun Apr 8 06:29:33 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 8 Apr 2007 06:29:33 +0200 (CEST) Subject: [Python-checkins] r54712 - in python/trunk: Doc/lib/libstdtypes.tex Misc/NEWS Message-ID: <20070408042933.E9C041E4009@bag.python.org> Author: brett.cannon Date: Sun Apr 8 06:29:32 2007 New Revision: 54712 Modified: python/trunk/Doc/lib/libstdtypes.tex python/trunk/Misc/NEWS Log: Doc that file.next() has undefined behaviour when called on a file opened with 'w'. Closes bug #1569057. To be backported once 2.5 branch is unfrozen. Modified: python/trunk/Doc/lib/libstdtypes.tex ============================================================================== --- python/trunk/Doc/lib/libstdtypes.tex (original) +++ python/trunk/Doc/lib/libstdtypes.tex Sun Apr 8 06:29:32 2007 @@ -1615,14 +1615,15 @@ iterator, typically in a \keyword{for} loop (for example, \code{for line in f: print line}), the \method{next()} method is called repeatedly. This method returns the next input line, or raises -\exception{StopIteration} when \EOF{} is hit. In order to make a -\keyword{for} loop the most efficient way of looping over the lines of -a file (a very common operation), the \method{next()} method uses a -hidden read-ahead buffer. As a consequence of using a read-ahead -buffer, combining \method{next()} with other file methods (like -\method{readline()}) does not work right. However, using -\method{seek()} to reposition the file to an absolute position will -flush the read-ahead buffer. +\exception{StopIteration} when \EOF{} is hit when the file is open for +reading (behavior is undefined when the file is open for writing). In +order to make a \keyword{for} loop the most efficient way of looping +over the lines of a file (a very common operation), the +\method{next()} method uses a hidden read-ahead buffer. As a +consequence of using a read-ahead buffer, combining \method{next()} +with other file methods (like \method{readline()}) does not work +right. However, using \method{seek()} to reposition the file to an +absolute position will flush the read-ahead buffer. \versionadded{2.3} \end{methoddesc} Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sun Apr 8 06:29:32 2007 @@ -736,6 +736,9 @@ Documentation ------------- +- Bug #1569057: Document that calling file.next() when the file is open for + writing is undefined. + - Patch #1489771: the syntax rules in Python Reference Manual were updated to reflect the current Python syntax. From nnorwitz at gmail.com Sun Apr 8 10:13:51 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sun, 8 Apr 2007 04:13:51 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070408081351.GA16204@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [482124 refs] From python-checkins at python.org Sun Apr 8 18:51:34 2007 From: python-checkins at python.org (guido.van.rossum) Date: Sun, 8 Apr 2007 18:51:34 +0200 (CEST) Subject: [Python-checkins] r54713 - peps/trunk/pep-3100.txt Message-ID: <20070408165134.A9B021E400A@bag.python.org> Author: guido.van.rossum Date: Sun Apr 8 18:51:33 2007 New Revision: 54713 Modified: peps/trunk/pep-3100.txt Log: Clarify what to use instead of callable(). Modified: peps/trunk/pep-3100.txt ============================================================================== --- peps/trunk/pep-3100.txt (original) +++ peps/trunk/pep-3100.txt Sun Apr 8 18:51:33 2007 @@ -179,7 +179,7 @@ * ``apply()``: use ``f(*args, **kw)`` instead [2]_ [done] * ``buffer()``: must die (use a bytes() type instead) (?) [2]_ -* ``callable()``: just call the object and catch the exception??? [2]_ +* ``callable()``: just use hasattr(x, '__call__') (?) [2]_ * ``compile()``: put in ``sys`` (or perhaps in a module of its own) [2]_ * ``coerce()``: no longer needed [2]_ * ``execfile()``, ``reload()``: use ``exec()`` [2]_ From nnorwitz at gmail.com Sun Apr 8 22:13:24 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sun, 8 Apr 2007 16:13:24 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070408201324.GA7876@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [482131 refs] From python-checkins at python.org Mon Apr 9 01:59:24 2007 From: python-checkins at python.org (collin.winter) Date: Mon, 9 Apr 2007 01:59:24 +0200 (CEST) Subject: [Python-checkins] r54716 - sandbox/trunk/2to3/fixes/fix_dict.py sandbox/trunk/2to3/fixes/util.py Message-ID: <20070408235924.36A441E4009@bag.python.org> Author: collin.winter Date: Mon Apr 9 01:59:23 2007 New Revision: 54716 Modified: sandbox/trunk/2to3/fixes/fix_dict.py sandbox/trunk/2to3/fixes/util.py Log: Add LParen and RParen macros. Modified: sandbox/trunk/2to3/fixes/fix_dict.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_dict.py (original) +++ sandbox/trunk/2to3/fixes/fix_dict.py Mon Apr 9 01:59:23 2007 @@ -26,7 +26,7 @@ import patcomp from pgen2 import token from fixes import basefix -from fixes.util import Name, Call, lparen_leaf, rparen_leaf +from fixes.util import Name, Call, LParen, RParen class FixDict(basefix.BaseFix): @@ -55,9 +55,7 @@ args = head + [pytree.Node(syms.trailer, [pytree.Leaf(token.DOT, '.'), Name(method)]), - pytree.Node(syms.trailer, - [lparen_leaf.clone(), - rparen_leaf.clone()])] + pytree.Node(syms.trailer, [LParen(), RParen()])] new = pytree.Node(syms.power, args) if not special: new.set_prefix("") Modified: sandbox/trunk/2to3/fixes/util.py ============================================================================== --- sandbox/trunk/2to3/fixes/util.py (original) +++ sandbox/trunk/2to3/fixes/util.py Mon Apr 9 01:59:23 2007 @@ -11,14 +11,16 @@ ass_leaf = Leaf(token.EQUAL, "=") ass_leaf.set_prefix(" ") -comma_leaf = Leaf(token.COMMA, ",") -lparen_leaf = Leaf(token.LPAR, "(") -rparen_leaf = Leaf(token.RPAR, ")") - ########################################################### ### Common node-construction "macros" ########################################################### +def LParen(): + return Leaf(token.LPAR, "(") + +def RParen(): + return Leaf(token.RPAR, ")") + def Assign(target, source): """Build an assignment statement""" if not isinstance(target, tuple): @@ -41,9 +43,9 @@ def Comma(): """A comma leaf""" - return comma_leaf.clone() + return Leaf(token.COMMA, ",") -def ArgList(args, lparen=lparen_leaf, rparen=rparen_leaf): +def ArgList(args, lparen=LParen(), rparen=RParen()): """A parenthesised argument list, used by Call()""" return Node(syms.trailer, [lparen.clone(), From python-checkins at python.org Mon Apr 9 03:01:11 2007 From: python-checkins at python.org (collin.winter) Date: Mon, 9 Apr 2007 03:01:11 +0200 (CEST) Subject: [Python-checkins] r54721 - in sandbox/trunk/2to3: pytree.py tests/test_pytree.py Message-ID: <20070409010111.80ADD1E4009@bag.python.org> Author: collin.winter Date: Mon Apr 9 03:01:09 2007 New Revision: 54721 Modified: sandbox/trunk/2to3/pytree.py sandbox/trunk/2to3/tests/test_pytree.py Log: Add a remove() method to pytree.Base. Modified: sandbox/trunk/2to3/pytree.py ============================================================================== --- sandbox/trunk/2to3/pytree.py (original) +++ sandbox/trunk/2to3/pytree.py Mon Apr 9 03:01:09 2007 @@ -131,6 +131,18 @@ if self.parent: self.parent.changed() self.was_changed = True + + def remove(self): + """Remove the node from the tree.""" + if self.parent: + children = list(self.parent.children) + for i, node in enumerate(self.parent.children): + if node is self: + self.parent.changed() + del children[i] + self.parent.children = tuple(children) + self.parent = None + break class Node(Base): Modified: sandbox/trunk/2to3/tests/test_pytree.py ============================================================================== --- sandbox/trunk/2to3/tests/test_pytree.py (original) +++ sandbox/trunk/2to3/tests/test_pytree.py Mon Apr 9 03:01:09 2007 @@ -177,6 +177,36 @@ self.assertEqual(n1.get_prefix(), prefix) self.assertEqual(l1.get_prefix(), prefix) self.assertEqual(l2.get_prefix(), "_") + + def testRemove(self): + l1 = pytree.Leaf(100, "foo") + n1 = pytree.Node(1000, [l1]) + n2 = pytree.Node(1000, [n1]) + + n1.remove() + self.failIf(n2 in n2.children) + self.assertEqual(l1.parent, n1) + self.assertEqual(n1.parent, None) + self.assertEqual(n2.parent, None) + self.failIf(n1.was_changed) + self.failUnless(n2.was_changed) + + l1.remove() + self.failIf(l1 in n1.children) + self.assertEqual(l1.parent, None) + self.assertEqual(n1.parent, None) + self.assertEqual(n2.parent, None) + self.failUnless(n1.was_changed) + self.failUnless(n2.was_changed) + + def testRemoveParentless(self): + n1 = pytree.Node(1000, []) + n1.remove() + self.assertEqual(n1.parent, None) + + l1 = pytree.Leaf(100, "foo") + l1.remove() + self.assertEqual(l1.parent, None) class TestPatterns(support.TestCase): From facundobatista at gmail.com Mon Apr 9 03:07:00 2007 From: facundobatista at gmail.com (Facundo Batista) Date: Sun, 8 Apr 2007 22:07:00 -0300 Subject: [Python-checkins] Python Regression Test Failures opt (1) In-Reply-To: References: <20070406081355.GA24121@python.psfb.org> Message-ID: 2007/4/6, Brett Cannon : > "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", > line 117, in testBasic > > self.assertEqual (i, "Foo\n") > > AssertionError: 'ERRO' != 'Foo\n' > ... > ... > Anyone know what caused these two tests to start failing? Sorry for the delay, I've been in a four days vacation here, and no internet connection. This is my fault, I added local test (using openssl) to test_socket_ssl.py. The problem for which that test fails should be fixed, though (I mean, you shouldn't be getting that error in current trunk). I checked with buildbots, and all pass the tests ok, except the following: - sparc-solaris10-gcc: test_socket_ssl skipped (socket module has no ssl support) - X86 XP: test_socket_ssl passes ok (fails in test_urllib). - X86 W2K: test_socket_ssl passes ok (fails in test_urllib). - X86 OpenBSD: does not check out from SVN. - Alpha True64 5.1: bad system call in test_posix, it doesn't get to test_socket_ssl. Neil, where did you see this fail? Regards, -- . Facundo Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org/ar/ From nnorwitz at gmail.com Mon Apr 9 03:30:09 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sun, 8 Apr 2007 18:30:09 -0700 Subject: [Python-checkins] Python Regression Test Failures opt (1) In-Reply-To: References: <20070406081355.GA24121@python.psfb.org> Message-ID: On 4/8/07, Facundo Batista wrote: > 2007/4/6, Brett Cannon : > > > "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", > > line 117, in testBasic > > > self.assertEqual (i, "Foo\n") > > > AssertionError: 'ERRO' != 'Foo\n' > > ... > > ... > > Anyone know what caused these two tests to start failing? > > Sorry for the delay, I've been in a four days vacation here, and no > internet connection. > > This is my fault, I added local test (using openssl) to > test_socket_ssl.py. The problem for which that test fails should be > fixed, though (I mean, you shouldn't be getting that error in current > trunk). > > I checked with buildbots, and all pass the tests ok, except the following: > > - sparc-solaris10-gcc: test_socket_ssl skipped (socket module has no > ssl support) > - X86 XP: test_socket_ssl passes ok (fails in test_urllib). > - X86 W2K: test_socket_ssl passes ok (fails in test_urllib). > - X86 OpenBSD: does not check out from SVN. > - Alpha True64 5.1: bad system call in test_posix, it doesn't get to > test_socket_ssl. > > Neil, where did you see this fail? Note: the machine that runs this is also one of the buildbots. The difference is that this is run in opt (ie, -O) mode. This script is Misc/build.sh. The relevant lines are: $PYTHON -O $REGRTEST_ARGS >& build/$F Which the only thing that's of interest is that python is run with -O. Hopefully if you run the test with -O you will be able to reproduce it. (Python is configured --with-pydebug.) n From python-checkins at python.org Mon Apr 9 03:49:31 2007 From: python-checkins at python.org (collin.winter) Date: Mon, 9 Apr 2007 03:49:31 +0200 (CEST) Subject: [Python-checkins] r54722 - in sandbox/trunk/2to3: fixes/fix_except.py fixes/fix_intern.py fixes/fix_raise.py fixes/fix_throw.py fixes/util.py pytree.py tests/test_pytree.py tests/test_util.py Message-ID: <20070409014931.7DD7E1E4009@bag.python.org> Author: collin.winter Date: Mon Apr 9 03:49:30 2007 New Revision: 54722 Modified: sandbox/trunk/2to3/fixes/fix_except.py sandbox/trunk/2to3/fixes/fix_intern.py sandbox/trunk/2to3/fixes/fix_raise.py sandbox/trunk/2to3/fixes/fix_throw.py sandbox/trunk/2to3/fixes/util.py sandbox/trunk/2to3/pytree.py sandbox/trunk/2to3/tests/test_pytree.py sandbox/trunk/2to3/tests/test_util.py Log: Convert node.children from a tuple to a list. Having it be a tuple meant jumping through casting hoops in order to modify the children; a list will enable more direct, more readable child manipulation. Modified: sandbox/trunk/2to3/fixes/fix_except.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_except.py (original) +++ sandbox/trunk/2to3/fixes/fix_except.py Mon Apr 9 03:49:30 2007 @@ -67,7 +67,7 @@ # Insert "old_N = new_N" as the first statement in # the except body. This loop skips leading whitespace # and indents - suite_stmts = list(e_suite.children) + suite_stmts = e_suite.children for i, stmt in enumerate(suite_stmts): if isinstance(stmt, pytree.Node): break @@ -81,7 +81,7 @@ assign.parent = e_suite suite_stmts = suite_stmts[:i] + [assign] + suite_stmts - e_suite.children = tuple(suite_stmts) + e_suite.children = suite_stmts children = [c.clone() for c in node.children[:3]] + try_cleanup return pytree.Node(node.type, children) Modified: sandbox/trunk/2to3/fixes/fix_intern.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_intern.py (original) +++ sandbox/trunk/2to3/fixes/fix_intern.py Mon Apr 9 03:49:30 2007 @@ -35,13 +35,12 @@ newarglist = pytree.Node(syms.arglist, [obj.clone()]) after = results["after"] if after: - after = tuple([n.clone() for n in after]) + after = [n.clone() for n in after] new = pytree.Node(syms.power, Attr(Name("sys"), Name("intern")) + - (pytree.Node(syms.trailer, + [pytree.Node(syms.trailer, [results["lpar"].clone(), newarglist, - results["rpar"].clone()]),) - + after) + results["rpar"].clone()])] + after) new.set_prefix(node.get_prefix()) return new Modified: sandbox/trunk/2to3/fixes/fix_raise.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_raise.py (original) +++ sandbox/trunk/2to3/fixes/fix_raise.py Mon Apr 9 03:49:30 2007 @@ -73,10 +73,8 @@ tb.set_prefix("") e = Call(exc, args) - with_tb = Attr(e, Name('with_traceback')) - call_wtb = list(with_tb + (ArgList([tb]),)) - - new = pytree.Node(syms.simple_stmt, [Name("raise")] + call_wtb) + with_tb = Attr(e, Name('with_traceback')) + [ArgList([tb])] + new = pytree.Node(syms.simple_stmt, [Name("raise")] + with_tb) new.set_prefix(node.get_prefix()) return new else: Modified: sandbox/trunk/2to3/fixes/fix_throw.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_throw.py (original) +++ sandbox/trunk/2to3/fixes/fix_throw.py Mon Apr 9 03:49:30 2007 @@ -52,9 +52,7 @@ tb.set_prefix("") e = Call(exc, args) - with_tb = Attr(e, Name('with_traceback')) - call_wtb = list(with_tb + (ArgList([tb]),)) - - throw_args.replace(pytree.Node(syms.power, call_wtb)) + with_tb = Attr(e, Name('with_traceback')) + [ArgList([tb])] + throw_args.replace(pytree.Node(syms.power, with_tb)) else: throw_args.replace(Call(exc, args)) Modified: sandbox/trunk/2to3/fixes/util.py ============================================================================== --- sandbox/trunk/2to3/fixes/util.py (original) +++ sandbox/trunk/2to3/fixes/util.py Mon Apr 9 03:49:30 2007 @@ -23,13 +23,13 @@ def Assign(target, source): """Build an assignment statement""" - if not isinstance(target, tuple): - target = (target,) - if not isinstance(source, tuple): + if not isinstance(target, list): + target = [target] + if not isinstance(source, list): source.set_prefix(" ") - source = (source,) + source = [source] - return Node(syms.atom, target + (ass_leaf.clone(),) + source) + return Node(syms.atom, target + [ass_leaf.clone()] + source) def Name(name, prefix=None): """Return a NAME leaf""" @@ -37,9 +37,8 @@ def Attr(obj, attr): """A node tuple for obj.attr""" - return (obj, - Node(syms.trailer, [Leaf(token.DOT, '.'), - attr])) + return [obj, + Node(syms.trailer, [Leaf(token.DOT, '.'), attr])] def Comma(): """A comma leaf""" @@ -157,9 +156,8 @@ return child elif child.type == syms.simple_stmt: if child.children[0].type == syms.expr_stmt: - n = _find(name, child.children[0].children[0]) - if n: - return n + if _find(name, child.children[0].children[0]): + return child.children[0] _block_syms = set([syms.funcdef, syms.classdef, syms.trailer]) def _find(name, node): Modified: sandbox/trunk/2to3/pytree.py ============================================================================== --- sandbox/trunk/2to3/pytree.py (original) +++ sandbox/trunk/2to3/pytree.py Mon Apr 9 03:49:30 2007 @@ -159,7 +159,7 @@ """ assert type >= 256, type self.type = type - self.children = tuple(children) + self.children = list(children) for ch in self.children: assert ch.parent is None, repr(ch) ch.parent = self @@ -435,7 +435,7 @@ assert content is None, repr(content) if content is not None: assert not isinstance(content, basestring), repr(content) - content = tuple(content) + content = list(content) for i, item in enumerate(content): assert isinstance(item, BasePattern), (i, item) if isinstance(item, WildcardPattern): @@ -548,7 +548,7 @@ if results is not None: results.update(r) if self.name: - results[self.name] = tuple(nodes) + results[self.name] = list(nodes) return True return False Modified: sandbox/trunk/2to3/tests/test_pytree.py ============================================================================== --- sandbox/trunk/2to3/tests/test_pytree.py (original) +++ sandbox/trunk/2to3/tests/test_pytree.py Mon Apr 9 03:49:30 2007 @@ -75,14 +75,14 @@ l2 = pytree.Leaf(200, "bar") n1 = pytree.Node(1000, [l1, l2]) self.assertEqual(n1.type, 1000) - self.assertEqual(n1.children, (l1, l2)) + self.assertEqual(n1.children, [l1, l2]) def testNodeRepr(self): l1 = pytree.Leaf(100, "foo") l2 = pytree.Leaf(100, "bar", context=(" ", (1, 0))) n1 = pytree.Node(1000, [l1, l2]) self.assertEqual(repr(n1), - "Node(1000, (%s, %s))" % (repr(l1), repr(l2))) + "Node(1000, [%s, %s])" % (repr(l1), repr(l2))) def testNodeStr(self): l1 = pytree.Leaf(100, "foo") @@ -121,7 +121,7 @@ l2 = pytree.Leaf(100, "+") l3 = pytree.Leaf(100, "bar") n1 = pytree.Node(1000, [l1, l2, l3]) - self.assertEqual(n1.children, (l1, l2, l3)) + self.assertEqual(n1.children, [l1, l2, l3]) self.failIf(n1.was_changed) l2new = pytree.Leaf(100, "-") l2.replace(l2new) @@ -271,12 +271,12 @@ self.assertEqual(sorted(r.keys()), ["pl", "pn", "pw"]) self.assertEqual(r["pl"], l1) self.assertEqual(r["pn"], n2) - self.assertEqual(r["pw"], (n2,)) + self.assertEqual(r["pw"], [n2]) # But this is equivalent - self.assertEqual(r, {"pl": l1, "pn": n2, "pw": (n2,)}) + self.assertEqual(r, {"pl": l1, "pn": n2, "pw": [n2]}) r = {} self.assertEqual(pw.match_seq([l1, l3], r), True) - self.assertEqual(r, {"pl": l3, "pw": (l1, l3)}) + self.assertEqual(r, {"pl": l3, "pw": [l1, l3]}) self.assert_(r["pl"] is l3) r = {} @@ -306,7 +306,7 @@ c, r = matches[0] self.assertEqual(c, 1) self.assertEqual(str(r["pr"]), "abcdef") - self.assertEqual(r["pw"], (la, lb, lc, ld, le, lf)) + self.assertEqual(r["pw"], [la, lb, lc, ld, le, lf]) for c in "abcdef": self.assertEqual(r["p" + c], pytree.Leaf(1, c)) @@ -318,10 +318,10 @@ l1 = pytree.Leaf(7, "(") l2 = pytree.Leaf(3, "x") l3 = pytree.Leaf(8, ")") - node = pytree.Node(331, (l1, l2, l3)) + node = pytree.Node(331, [l1, l2, l3]) r = {} self.assert_(pattern.match(node, r)) - self.assertEqual(r["args"], (l2,)) + self.assertEqual(r["args"], [l2]) if __name__ == "__main__": Modified: sandbox/trunk/2to3/tests/test_util.py ============================================================================== --- sandbox/trunk/2to3/tests/test_util.py (original) +++ sandbox/trunk/2to3/tests/test_util.py Mon Apr 9 03:49:30 2007 @@ -71,7 +71,7 @@ from fixes.util import Attr, Name attr = Attr(Name("a"), Name("b")) - self.assertEqual(type(attr), tuple) + self.assertEqual(type(attr), list) class Test_Name(MacroTestCase): From python-checkins at python.org Mon Apr 9 06:43:59 2007 From: python-checkins at python.org (collin.winter) Date: Mon, 9 Apr 2007 06:43:59 +0200 (CEST) Subject: [Python-checkins] r54723 - in sandbox/trunk/2to3: pytree.py tests/test_pytree.py Message-ID: <20070409044359.F31651E400B@bag.python.org> Author: collin.winter Date: Mon Apr 9 06:43:55 2007 New Revision: 54723 Modified: sandbox/trunk/2to3/pytree.py sandbox/trunk/2to3/tests/test_pytree.py Log: Make pytree.Base.remove() return the old node index. Modified: sandbox/trunk/2to3/pytree.py ============================================================================== --- sandbox/trunk/2to3/pytree.py (original) +++ sandbox/trunk/2to3/pytree.py Mon Apr 9 06:43:55 2007 @@ -133,16 +133,15 @@ self.was_changed = True def remove(self): - """Remove the node from the tree.""" + """Remove the node from the tree. Returns the position of the node + in its parent's children before it was removed.""" if self.parent: - children = list(self.parent.children) for i, node in enumerate(self.parent.children): if node is self: self.parent.changed() - del children[i] - self.parent.children = tuple(children) + del self.parent.children[i] self.parent = None - break + return i class Node(Base): Modified: sandbox/trunk/2to3/tests/test_pytree.py ============================================================================== --- sandbox/trunk/2to3/tests/test_pytree.py (original) +++ sandbox/trunk/2to3/tests/test_pytree.py Mon Apr 9 06:43:55 2007 @@ -180,18 +180,20 @@ def testRemove(self): l1 = pytree.Leaf(100, "foo") - n1 = pytree.Node(1000, [l1]) + l2 = pytree.Leaf(100, "foo") + n1 = pytree.Node(1000, [l1, l2]) n2 = pytree.Node(1000, [n1]) - - n1.remove() - self.failIf(n2 in n2.children) + + self.assertEqual(n1.remove(), 0) + self.failIf(n1 in n2.children) self.assertEqual(l1.parent, n1) self.assertEqual(n1.parent, None) self.assertEqual(n2.parent, None) self.failIf(n1.was_changed) self.failUnless(n2.was_changed) - - l1.remove() + + self.assertEqual(l2.remove(), 1) + self.assertEqual(l1.remove(), 0) self.failIf(l1 in n1.children) self.assertEqual(l1.parent, None) self.assertEqual(n1.parent, None) From python-checkins at python.org Mon Apr 9 07:51:33 2007 From: python-checkins at python.org (nick.coghlan) Date: Mon, 9 Apr 2007 07:51:33 +0200 (CEST) Subject: [Python-checkins] r54724 - peps/trunk/pep-0000.txt peps/trunk/pep-3118.txt Message-ID: <20070409055133.DCF741E4009@bag.python.org> Author: nick.coghlan Date: Mon Apr 9 07:51:32 2007 New Revision: 54724 Added: peps/trunk/pep-3118.txt (contents, props changed) Modified: peps/trunk/pep-0000.txt Log: Add enhanced buffer interface PEP from Travis Oliphant Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Mon Apr 9 07:51:32 2007 @@ -116,7 +116,7 @@ S 3114 Renaming iterator.next() to iterator.__next__() Yee S 3116 New I/O Stutzbach, Verdone, GvR S 3117 Postfix Type Declarations Brandl - + S 3118 Revising the buffer protocol Oliphant, Banks Finished PEPs (done, implemented in Subversion) @@ -470,6 +470,7 @@ SA 3115 Metaclasses in Python 3000 Talin S 3116 New I/O Stutzbach, Verdone, GvR S 3117 Postfix Type Declarations Brandl + S 3118 Revising the buffer protocol Oliphant, Banks Key @@ -495,6 +496,7 @@ Altis, Kevin altis at semi-retired.com Ascher, David davida at activestate.com Astrand, Peter astrand at lysator.liu.se + Banks, Carl pythondev at aerojockey.com Barrett, Paul barrett at stsci.edu Batista, Facundo facundo at taniquetil.com.ar Baxter, Anthony anthony at interlink.com.au Added: peps/trunk/pep-3118.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-3118.txt Mon Apr 9 07:51:32 2007 @@ -0,0 +1,608 @@ +PEP: 3118 +Title: Revising the buffer protocol +Version: $Revision$ +Last-Modified: $Date$ +Authors: Travis Oliphant , Carl Banks +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 28-Aug-2006 +Python-Version: 3000 + +Abstract +======== + +This PEP proposes re-designing the buffer interface (PyBufferProcs +function pointers) to improve the way Python allows memory sharing +in Python 3.0 + +In particular, it is proposed that the character buffer portion +of the API be elminated and the multiple-segment portion be +re-designed in conjunction with allowing for strided memory +to be shared. In addition, the new buffer interface will +allow the sharing of any multi-dimensional nature of the +memory and what data-format the memory contains. + +This interface will allow any extension module to either +create objects that share memory or create algorithms that +use and manipulate raw memory from arbitrary objects that +export the interface. + + +Rationale +========= + +The Python 2.X buffer protocol allows different Python types to +exchange a pointer to a sequence of internal buffers. This +functionality is *extremely* useful for sharing large segments of +memory between different high-level objects, but it is too limited and +has issues: + +1. There is the little used "sequence-of-segments" option + (bf_getsegcount) that is not well motivated. + +2. There is the apparently redundant character-buffer option + (bf_getcharbuffer) + +3. There is no way for a consumer to tell the buffer-API-exporting + object it is "finished" with its view of the memory and + therefore no way for the exporting object to be sure that it is + safe to reallocate the pointer to the memory that it owns (for + example, the array object reallocating its memory after sharing + it with the buffer object which held the original pointer led + to the infamous buffer-object problem). + +4. Memory is just a pointer with a length. There is no way to + describe what is "in" the memory (float, int, C-structure, etc.) + +5. There is no shape information provided for the memory. But, + several array-like Python types could make use of a standard + way to describe the shape-interpretation of the memory + (wxPython, GTK, pyQT, CVXOPT, PyVox, Audio and Video + Libraries, ctypes, NumPy, data-base interfaces, etc.) + +6. There is no way to share discontiguous memory (except through + the sequence of segments notion). + + There are two widely used libraries that use the concept of + discontiguous memory: PIL and NumPy. Their view of discontiguous + arrays is different, though. The proposed buffer interface allows + sharing of either memory model. Exporters will use only one + approach and consumers may choose to support discontiguous + arrays of each type however they choose. + + NumPy uses the notion of constant striding in each dimension as its + basic concept of an array. With this concept, a simple sub-region + of a larger array can be described without copying the data. T + Thus, stride information is the additional information that must be + shared. + + The PIL uses a more opaque memory representation. Sometimes an + image is contained in a contiguous segment of memory, but sometimes + it is contained in an array of pointers to the contiguous segments + (usually lines) of the image. The PIL is where the idea of multiple + buffer segments in the original buffer interface came from. + + NumPy's strided memory model is used more often in computational + libraries and because it is so simple it makes sense to support + memory sharing using this model. The PIL memory model is sometimes + used in C-code where a 2-d array can be then accessed using double + pointer indirection: e.g. image[i][j]. + + The buffer interface should allow the object to export either of these + memory models. Consumers are free to either require contiguous memory + or write code to handle one or both of these memory models. + +Proposal Overview +================= + +* Eliminate the char-buffer and multiple-segment sections of the + buffer-protocol. + +* Unify the read/write versions of getting the buffer. + +* Add a new function to the interface that should be called when + the consumer object is "done" with the memory area. + +* Add a new variable to allow the interface to describe what is in + memory (unifying what is currently done now in struct and + array) + +* Add a new variable to allow the protocol to share shape information + +* Add a new variable for sharing stride information + +* Add a new mechanism for sharing arrays that must + be accessed using pointer indirection. + +* Fix all objects in the core and the standard library to conform + to the new interface + +* Extend the struct module to handle more format specifiers + +* Extend the buffer object into a new memory object which places + a Python veneer around the buffer interface. + +* Add a few functions to make it easy to copy contiguous data + in and out of object supporting the buffer interface. + +Specification +============= + +While the new specification allows for complicated memory sharing. +Simple contiguous buffers of bytes can still be obtained from an +object. In fact, the new protocol allows a standard mechanism for +doing this even if the original object is not represented as a +contiguous chunk of memory. + +The easiest way is to use the provided C-API to obtain a contiguous +chunk of memory like the old buffer protocol allowed. + + +Change the PyBufferProcs structure to + +:: + + typedef struct { + getbufferproc bf_getbuffer; + releasebufferproc bf_releasebuffer; + } + + +:: + + typedef int (*getbufferproc)(PyObject *obj, struct bufferinfo *view) + +This function returns 0 on success and -1 on failure (and raises an +error). The first variable is the "exporting" object. The second +argument is the address to a bufferinfo structure. If view is NULL, +then no information is returned but a lock on the memory is still +obtained. In this case, releasebuffer should also be called with NULL. + +The bufferinfo structure is:: + + struct bufferinfo { + void *buf; + Py_ssize_t len; + int readonly; + char *format; + int ndims; + Py_ssize_t *shape; + Py_ssize_t *strides; + Py_ssize_t *suboffsets; + }; + +Upon return from getbufferproc, the bufferinfo structure is filled in +with relevant information about the buffer. This same bufferinfo +structure must be passed to bf_releasebuffer (if available) when the +consumer is done with the memory. The caller is responsible for +keeping a reference to obj until releasebuffer is called. + + +The members of the bufferinfo structure are: + + +buf + a pointer to the start of the memory for the object + +len + the total bytes of memory the object uses. This should be the + same as the product of the shape array multiplied by the number of + bytes per item of memory. + +readonly + an integer variable to hold whether or not the memory is + readonly. 1 means the memory is readonly, zero means the + memory is writeable. + + +format + a format-string (following extended struct syntax) indicating what + is in each element of of memory. The number of elements is len / + itemsize, where itemsize is the number of bytes implied by the + format. For standard unsigned bytes use a format string of "B". + +ndims + a variable storing the number of dimensions the memory represents. + Should be >=0. + +shape + an array of ``Py_ssize_t`` of length ``ndims`` indicating the + shape of the memory as an N-D array. Note that ``((*shape)[0] * + ... * (*shape)[ndims-1])*itemsize = len``. This can be NULL + to indicate 1-d arrays. + +strides + address of a ``Py_ssize_t*`` variable that will be filled with a + pointer to an array of ``Py_ssize_t`` of length ``*ndims`` + indicating the number of bytes to skip to get to the next element + in each dimension. If this is NULL, then the memory is assumed to + be C-style contigous with the last dimension varying the fastest. + +suboffsets + address of a ``Py_ssize_t *`` variable that will be filled with a + pointer to an array of ``Py_ssize_t`` of length ``*ndims``. If + these suboffset numbers are >=0, then the value stored along the + indicated dimension is a pointer and the suboffset value dictates + how many bytes to add to the pointer after de-referencing. A + suboffset value that it negative indicates that no de-referencing + should occur (striding in a contiguous memory block). If all + suboffsets are negative (i.e. no de-referencing is needed, then + this must be NULL. + + For clarity, here is a function that returns a pointer to the + element in an N-D array pointed to by an N-dimesional index when + there are both strides and suboffsets.:: + + void* get_item_pointer(int ndim, void* buf, Py_ssize_t* strides, + Py_ssize_t* suboffsets, Py_ssize_t *indices) { + char* pointer = (char*)buf; + int i; + for (i = 0; i < ndim; i++) { + pointer += strides[i]*indices[i]; + if (suboffsets[i] >=0 ) { + pointer = *((char**)pointer) + suboffsets[i]; + } + } + return (void*)pointer; + } + + Notice the suboffset is added "after" the dereferencing occurs. + Thus slicing in the ith dimension would add to the suboffsets in + the i-1st dimension. Slicing in the first dimension would change + the location of the starting pointer directly (i.e. buf would + be modified). + + +The exporter is responsible for making sure the memory pointed to by +buf, format, shape, strides, and suboffsets is valid until +releasebuffer is called. If the exporter wants to be able to change +shape, strides, and/or suboffsets before releasebuffer is called then +it should allocate those arrays when getbuffer is called and free them +when releasebuffer is called. + + +The same bufferinfo struct should be used in the other buffer +interface call. The caller is responsible for the memory of the +bufferinfo object itself. + +``typedef int (*releasebufferproc)(PyObject *obj, struct bufferinfo *view)`` + Callers of getbufferproc must make sure that this function is + called when memory previously acquired from the object is no + longer needed. The exporter of the interface must make sure that + any memory pointed to in the bufferinfo structure remains valid + until releasebuffer is called. + + Both of these routines are optional for a type object + + If the releasebuffer function is not provided then it does not ever + need to be called. + +Exporters will need to define a releasebuffer function if they can +re-allocate their memory, strides, shape, suboffsets, or format +variables which they might share through the struct bufferinfo. +Several mechanisms could be used to keep track of how many getbuffer +calls have been made and shared. Either a single variable could be +used to keep track of how many "views" have been exported, or a +linked-list of bufferinfo structures filled in could be maintained in +each objet. All that is needed is to ensure that any memory shared +through the bufferinfo structure remains valid until releasebuffer is +called on that memory. + + +New C-API calls are proposed +============================ + +:: + + int PyObject_CheckBuffer(PyObject *obj) + +Return 1 if the getbuffer function is available otherwise 0. + +:: + + PyObject *PyObject_GetBuffer(PyObject *obj) + +Return a memory-view object from an object that defines the buffer interface. +If make_ro is non-zero then request that the memory is made read-only until +release buffer is called. + +A memory-view object is an extended buffer object that should replace +the buffer object in Python 3K. It's C-structure is:: + + typedef struct { + PyObject_HEAD + PyObject *base; + struct bufferinfo view; + int itemsize; + int flags; + } PyMemoryViewObject; + +This is very similar to the current buffer object except offset has +been removed because ptr can just be modified by offset and a single +offset is not sufficient. Also the hash has been removed because +using the buffer object as a hash even if it is read-only is rarely +useful. + +Also, the format, ndims, shape, strides, and suboffsets have been +added. These additions will allow multi-dimensional slicing of the +memory-view object which can be added at some point. This object +always owns it's own shape, strides, and suboffsets arrays and it's +own format string, but always borrows the memory from the object +pointed to by base. + +The itemsize is a convenience and specifies the number of bytes +indicated by the format string if positive. + +This object never reallocates ptr, shape, strides, subboffsets or +format and therefore does not need to keep track of how many views it +has exported. + +It exports a view using the base object. It releases a view by releasing +the view on the base object. Because, it will never re-allocate memory, +it does not need to keep track of how many it has exported but simple +reference counting will suffice. + +:: + + int PyObject_SizeFromFormat(char *) + +Return the implied itemsize of the data-format area from a struct-style +description. + +:: + + int PyObject_GetContiguous(PyObject *obj, void **buf, Py_ssize_t *len, + int fortran) + +Return a contiguous chunk of memory representing the buffer. If a +copy is made then return 1. If no copy was needed return 0. If an +error occurred in probing the buffer interface, then return -1. The +contiguous chunk of memory is pointed to by ``*buf`` and the length of +that memory is ``*len``. If the object is multi-dimensional, then if +fortran is 1, the first dimension of the underlying array will vary +the fastest in the buffer. If fortran is 0, then the last dimension +will vary the fastest (C-style contiguous). If fortran is -1, then it +does not matter and you will get whatever the object decides is easiest. + +:: + + int PyObject_CopyToObject(PyObject *obj, void *buf, Py_ssize_t len, + int fortran) + +Copy ``len`` bytes of data pointed to by the contiguous chunk of +memory pointed to by ``buf`` into the buffer exported by obj. Return +0 on success and return -1 and raise an error on failure. If the +object does not have a writeable buffer, then an error is raised. If +fortran is 1, then if the object is multi-dimensional, then the data +will be copied into the array in Fortran-style (first dimension varies +the fastest). If fortran is 0, then the data will be copied into the +array in C-style (last dimension varies the fastest). If fortran is -1, then +it does not matter and the copy will be made in whatever way is +easiest. + +The last two C-API calls allow a standard way of getting data in and +out of Python objects into contiguous memory areas no matter how it is +actually stored. These calls use the extended buffer interface to perform +their work. + +:: + + int PyObject_IsContiguous(struct bufferinfo *view); + +Return 1 if the memory defined by the view object is C-style +contiguous. Return 0 otherwise. + +:: + + void PyObject_FillContiguousStrides(int *ndims, Py_ssize_t *shape, + int itemsize, + Py_ssize_t *strides) + +Fill the strides array with byte-strides of a contiguous array of the +given shape with the given number of bytes per element. + + + +Additions to the struct string-syntax +===================================== + +The struct string-syntax is missing some characters to fully +implement data-format descriptions already available elsewhere (in +ctypes and NumPy for example). The Python 2.5 specification is +at http://docs.python.org/lib/module-struct.html + +Here are the proposed additions: + + +================ =========== +Character Description +================ =========== +'t' bit (number before states how many bits) +'?' platform _Bool type +'g' long double +'c' ucs-1 (latin-1) encoding +'u' ucs-2 +'w' ucs-4 +'O' pointer to Python Object +'Z' complex (whatever the next specifier is) +'&' specific pointer (prefix before another charater) +'T{}' structure (detailed layout inside {}) +'(k1,k2,...,kn)' multi-dimensional array of whatever follows +':name:' optional name of the preceeding element +'X{}' pointer to a function (optional function + signature inside {}) +' ' ignored (allow better readability) +================ =========== + +The struct module will be changed to understand these as well and +return appropriate Python objects on unpacking. Un-packing a +long-double will return a decimal object. Unpacking 'u' or +'w' will return Python unicode. Unpacking a multi-dimensional +array will return a list of lists. Un-packing a pointer will +return a ctypes pointer object. Un-packing a bit will return a +Python Bool. Spaces in the struct-string syntax will be ignored. +Unpacking a named-object will return a Python class with attributes +having those names. + +Endian-specification ('=','>','<') is also allowed inside the +string so that it can change if needed. The previously-specified +endian string is in force until changed. The default endian is '='. + +According to the struct-module, a number can preceed a character +code to specify how many of that type there are. The +(k1,k2,...,kn) extension also allows specifying if the data is +supposed to be viewed as a (C-style contiguous, last-dimension +varies the fastest) multi-dimensional array of a particular format. + +Functions should be added to ctypes to create a ctypes object from +a struct description, and add long-double, and ucs-2 to ctypes. + +Examples of Data-Format Descriptions +==================================== + +Here are some examples of C-structures and how they would be +represented using the struct-style syntax: + +float + 'f' +complex double + 'Zd' +RGB Pixel data + 'BBB' or 'B:r: B:g: B:b:' +Mixed endian (weird but possible) + '>i:big: buf = self->lines; + view->len = self->height*self->width; + view->readonly = 0; + view->ndims = 2; + self->shape_array[0] = height; + self->shape_array[1] = width; + view->shape = &self->shape_array; + self->stride_array[0] = sizeof(struct rgba*); + self->stride_array[1] = sizeof(struct rgba); + view->strides = &self->stride_array; + view->suboffsets = suboffsets; + + self->view_count ++; + + return 0; + } + + + int Image_releasebuffer(PyObject *self, struct bufferinfo *view) { + self->view_count--; + return 0; + } + + + +Copyright +========= + +This PEP is placed in the public domain + From nnorwitz at gmail.com Mon Apr 9 10:13:17 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Mon, 9 Apr 2007 04:13:17 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070409081317.GA30819@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [482115 refs] From python-checkins at python.org Mon Apr 9 11:03:04 2007 From: python-checkins at python.org (georg.brandl) Date: Mon, 9 Apr 2007 11:03:04 +0200 (CEST) Subject: [Python-checkins] r54725 - peps/trunk/pep-3117.txt Message-ID: <20070409090304.42F2E1E400A@bag.python.org> Author: georg.brandl Date: Mon Apr 9 11:03:03 2007 New Revision: 54725 Modified: peps/trunk/pep-3117.txt (contents, props changed) Log: Add missing keywords. Modified: peps/trunk/pep-3117.txt ============================================================================== --- peps/trunk/pep-3117.txt (original) +++ peps/trunk/pep-3117.txt Mon Apr 9 11:03:03 2007 @@ -1,7 +1,7 @@ PEP: 3117 Title: Postfix type declarations -Version: $Revision: $ -Last-Modified: $Date: $ +Version: $Revision$ +Last-Modified: $Date$ Author: Georg Brandl Status: Draft Type: Standards Track From python-checkins at python.org Mon Apr 9 18:16:14 2007 From: python-checkins at python.org (vinay.sajip) Date: Mon, 9 Apr 2007 18:16:14 +0200 (CEST) Subject: [Python-checkins] r54726 - python/trunk/Lib/logging/handlers.py Message-ID: <20070409161614.8446F1E400A@bag.python.org> Author: vinay.sajip Date: Mon Apr 9 18:16:10 2007 New Revision: 54726 Modified: python/trunk/Lib/logging/handlers.py Log: Added optional timeout to SocketHandler.makeSocket (SF #1695948) Modified: python/trunk/Lib/logging/handlers.py ============================================================================== --- python/trunk/Lib/logging/handlers.py (original) +++ python/trunk/Lib/logging/handlers.py Mon Apr 9 18:16:10 2007 @@ -361,12 +361,14 @@ self.retryMax = 30.0 self.retryFactor = 2.0 - def makeSocket(self): + def makeSocket(self, timeout=1): """ A factory method which allows subclasses to define the precise type of socket they want. """ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if hasattr(s, 'settimeout'): + s.settimeout(timeout) s.connect((self.host, self.port)) return s From buildbot at python.org Mon Apr 9 18:42:04 2007 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Apr 2007 16:42:04 +0000 Subject: [Python-checkins] buildbot warnings in x86 mvlgcc trunk Message-ID: <20070409164204.875751E400A@bag.python.org> The Buildbot has detected a new failure of x86 mvlgcc trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520mvlgcc%2520trunk/builds/449 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon,vinay.sajip Build had warnings: warnings test Excerpt from the test logfile: Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 93, in run svr.serve_a_few() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 35, in serve_a_few self.handle_request() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 224, in handle_request self.handle_error(request, client_address) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 222, in handle_request self.process_request(request, client_address) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 429, in process_request self.collect_children() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 425, in collect_children self.active_children.remove(pid) ValueError: list.remove(x): x not in list Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 1 test failed: test_socketserver make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Apr 9 21:10:31 2007 From: python-checkins at python.org (ziga.seilnacht) Date: Mon, 9 Apr 2007 21:10:31 +0200 (CEST) Subject: [Python-checkins] r54727 - python/trunk/Lib/test/test_urllib.py Message-ID: <20070409191031.E9D7C1E4014@bag.python.org> Author: ziga.seilnacht Date: Mon Apr 9 21:10:29 2007 New Revision: 54727 Modified: python/trunk/Lib/test/test_urllib.py Log: Patch #1695862: remove old test directory that causes test_urllib failures on Windows buildbots. The change is a one time fix and will be removed after a successful buildbot run. Modified: python/trunk/Lib/test/test_urllib.py ============================================================================== --- python/trunk/Lib/test/test_urllib.py (original) +++ python/trunk/Lib/test/test_urllib.py Mon Apr 9 21:10:29 2007 @@ -547,6 +547,20 @@ def test_main(): + # cleanup old test dir on Windows buildbots + old_test_path = test_support.TESTFN + ".2" + if os.path.isdir(old_test_path): + for root, dirs, files in os.walk(old_test_path, topdown=False): + for name in files: + os.remove(os.path.join(root, name)) + for name in dirs: + dirname = os.path.join(root, name) + if not os.path.islink(dirname): + os.rmdir(dirname) + else: + os.remove(dirname) + os.rmdir(old_test_path) + test_support.run_unittest( urlopen_FileTests, urlopen_HttpTests, From nnorwitz at gmail.com Mon Apr 9 22:13:44 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Mon, 9 Apr 2007 16:13:44 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20070409201344.GA19138@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [9008 refs] test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test test_socket_ssl failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 117, in testBasic self.assertEqual(i, "Foo\n") AssertionError: 'ERRO' != 'Foo\n' test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort Exception in thread Thread-43: Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/threading.py", line 460, in __bootstrap self.run() File "/tmp/python-test/local/lib/python2.6/test/test_socket_ssl.py", line 163, in run self.s.stdin.write(l) IOError: [Errno 32] Broken pipe test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 297 tests OK. 1 test failed: test_socket_ssl 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_gl test_imgfile test_ioctl test_linuxaudiodev test_macfs test_macostools test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl [482130 refs] From python-checkins at python.org Tue Apr 10 05:00:43 2007 From: python-checkins at python.org (facundo.batista) Date: Tue, 10 Apr 2007 05:00:43 +0200 (CEST) Subject: [Python-checkins] r54729 - python/trunk/Lib/test/test_socket_ssl.py Message-ID: <20070410030043.DBDED1E400D@bag.python.org> Author: facundo.batista Date: Tue Apr 10 05:00:37 2007 New Revision: 54729 Modified: python/trunk/Lib/test/test_socket_ssl.py Log: Minor fix to the tests pass ok even with -O. Modified: python/trunk/Lib/test/test_socket_ssl.py ============================================================================== --- python/trunk/Lib/test/test_socket_ssl.py (original) +++ python/trunk/Lib/test/test_socket_ssl.py Tue Apr 10 05:00:37 2007 @@ -150,7 +150,8 @@ s = socket.socket() s.connect(("localhost", 4433)) s.close() - assert self.s.stdout.readline() == "ERROR\n" + if self.s.stdout.readline() != "ERROR\n": + raise ValuError except: self.haveServer = False else: From facundobatista at gmail.com Tue Apr 10 05:29:06 2007 From: facundobatista at gmail.com (Facundo Batista) Date: Tue, 10 Apr 2007 00:29:06 -0300 Subject: [Python-checkins] Python Regression Test Failures opt (1) In-Reply-To: References: <20070406081355.GA24121@python.psfb.org> Message-ID: 2007/4/8, Neal Norwitz : > Note: the machine that runs this is also one of the buildbots. The > difference is that this is run in opt (ie, -O) mode. This script is > Misc/build.sh. The relevant lines are: > $PYTHON -O $REGRTEST_ARGS >& build/$F > > Which the only thing that's of interest is that python is run with -O. > Hopefully if you run the test with -O you will be able to reproduce Aha! It was an assert, that as wasn't being used, just skipped an important readline(). Failed also in my machine when running with -O. Changed it, commited it. I see everything OK. Could you p-p-please check again? Regards, -- . Facundo Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org/ar/ From python-checkins at python.org Tue Apr 10 06:44:54 2007 From: python-checkins at python.org (collin.winter) Date: Tue, 10 Apr 2007 06:44:54 +0200 (CEST) Subject: [Python-checkins] r54730 - python/trunk/Lib/test/test_socket_ssl.py Message-ID: <20070410044454.248981E400D@bag.python.org> Author: collin.winter Date: Tue Apr 10 06:44:49 2007 New Revision: 54730 Modified: python/trunk/Lib/test/test_socket_ssl.py Log: Typo fix. Modified: python/trunk/Lib/test/test_socket_ssl.py ============================================================================== --- python/trunk/Lib/test/test_socket_ssl.py (original) +++ python/trunk/Lib/test/test_socket_ssl.py Tue Apr 10 06:44:49 2007 @@ -151,7 +151,7 @@ s.connect(("localhost", 4433)) s.close() if self.s.stdout.readline() != "ERROR\n": - raise ValuError + raise ValueError except: self.haveServer = False else: From python-checkins at python.org Tue Apr 10 11:45:07 2007 From: python-checkins at python.org (nick.coghlan) Date: Tue, 10 Apr 2007 11:45:07 +0200 (CEST) Subject: [Python-checkins] r54731 - peps/trunk/pep-3118.txt Message-ID: <20070410094507.510E81E400D@bag.python.org> Author: nick.coghlan Date: Tue Apr 10 11:45:04 2007 New Revision: 54731 Modified: peps/trunk/pep-3118.txt Log: PEP 3118 updates from Travis Modified: peps/trunk/pep-3118.txt ============================================================================== --- peps/trunk/pep-3118.txt (original) +++ peps/trunk/pep-3118.txt Tue Apr 10 11:45:04 2007 @@ -135,8 +135,8 @@ doing this even if the original object is not represented as a contiguous chunk of memory. -The easiest way is to use the provided C-API to obtain a contiguous -chunk of memory like the old buffer protocol allowed. +The easiest way to obtain a simple contiguous chunk of memory is +to use the provided C-API to obtain a chunk of memory. Change the PyBufferProcs structure to @@ -151,13 +151,64 @@ :: - typedef int (*getbufferproc)(PyObject *obj, struct bufferinfo *view) + typedef int (*getbufferproc)(PyObject *obj, struct bufferinfo *view, int flags) This function returns 0 on success and -1 on failure (and raises an error). The first variable is the "exporting" object. The second argument is the address to a bufferinfo structure. If view is NULL, then no information is returned but a lock on the memory is still -obtained. In this case, releasebuffer should also be called with NULL. +obtained. In this case, the corresponding releasebuffer should also +be called with NULL. + +The third argument indicates what kind of buffer the exporter is allowed to return. It tells the +exporter what elements the bufferinfo structure the consumer is going to make use of. This +allows the exporter to simplify and/or raise an error if it can't support the operation. + +It also allows the caller to make a request for a simple "view" and +receive it or have an error raised if it's not possible. + +All of the following assume that at least buf, len, and readonly will be +utilized by the caller. + + Py_BUF_SIMPLE + The returned buffer will only be assumed to be readable (the object + may or may not have writeable memory). Only the buf, len, and + readonly variables may be accessed. The format will be + assumed to be unsigned bytes. This is a "stand-alone" flag constant. + It never needs to be \|'d to the others. + + Py_BUF_WRITEABLE + The returned buffer must be writeable. If it cannot be, then raise an error. + + Py_BUF_READONLY + The returned buffer must be readonly and the underlying object should make + its memory readonly if that is possible. + + Py_BUF_FORMAT + The consumer will be using the format string information so make sure that + member is filled correctly. + + Py_BUF_SHAPE + The consumer can (and might) make use of using the ndims and shape members of the structure + so make sure they are filled in correctly. + + Py_BUF_STRIDES (implies SHAPE) + The consumer can (and might) make use of the strides member of the structure (as well + as ndims and shape) + + Py_BUF_OFFSETS (implies STRIDES) + The consumer can (and might) make use of the suboffsets member (as well as + ndims, shape, and strides) + +Thus, the consumer simply wanting an contiguous chunk of bytes from +the object would use Py_BUF_SIMPLE, while a consumer that understands +how to make use of the most complicated cases would use +Py_BUF_OFFSETS. + +There is a C-API that simple exporting objects can use to fill-in the +buffer info structure correctly according to the provided flags if a +contiguous chunk of memory is all that can be exported. + The bufferinfo structure is:: @@ -170,18 +221,19 @@ Py_ssize_t *shape; Py_ssize_t *strides; Py_ssize_t *suboffsets; + void *internal; }; -Upon return from getbufferproc, the bufferinfo structure is filled in +Before calling this function, the bufferinfo structure can be filled with +whatever. Upon return from getbufferproc, the bufferinfo structure is filled in with relevant information about the buffer. This same bufferinfo structure must be passed to bf_releasebuffer (if available) when the consumer is done with the memory. The caller is responsible for -keeping a reference to obj until releasebuffer is called. - +keeping a reference to obj until releasebuffer is called (i.e. this +call does not alter the reference count of obj). The members of the bufferinfo structure are: - buf a pointer to the start of the memory for the object @@ -195,29 +247,28 @@ readonly. 1 means the memory is readonly, zero means the memory is writeable. - -format - a format-string (following extended struct syntax) indicating what - is in each element of of memory. The number of elements is len / - itemsize, where itemsize is the number of bytes implied by the - format. For standard unsigned bytes use a format string of "B". +format + a NULL-terminated format-string (following the struct-style syntax + including extensions) indicating what is in each element of + memory. The number of elements is len / itemsize, where itemsize + is the number of bytes implied by the format. For standard + unsigned bytes use a format string of "B". ndims a variable storing the number of dimensions the memory represents. - Should be >=0. + Must be >=0. shape an array of ``Py_ssize_t`` of length ``ndims`` indicating the shape of the memory as an N-D array. Note that ``((*shape)[0] * - ... * (*shape)[ndims-1])*itemsize = len``. This can be NULL - to indicate 1-d arrays. + ... * (*shape)[ndims-1])*itemsize = len``. strides address of a ``Py_ssize_t*`` variable that will be filled with a pointer to an array of ``Py_ssize_t`` of length ``*ndims`` indicating the number of bytes to skip to get to the next element - in each dimension. If this is NULL, then the memory is assumed to - be C-style contigous with the last dimension varying the fastest. + in each dimension. For C-style contiguous arrays (where the + last-dimension varies the fastest) this must be filled in. suboffsets address of a ``Py_ssize_t *`` variable that will be filled with a @@ -249,22 +300,30 @@ Notice the suboffset is added "after" the dereferencing occurs. Thus slicing in the ith dimension would add to the suboffsets in - the i-1st dimension. Slicing in the first dimension would change + the (i-1)st dimension. Slicing in the first dimension would change the location of the starting pointer directly (i.e. buf would be modified). + +internal + This is for use internally by the exporting object. For example, + this might be re-cast as an integer by the exporter and used to + store flags about whether or not the shape, strides, and suboffsets + arrays must be freed when the buffer is released. The consumer + should never touch this value. The exporter is responsible for making sure the memory pointed to by buf, format, shape, strides, and suboffsets is valid until releasebuffer is called. If the exporter wants to be able to change shape, strides, and/or suboffsets before releasebuffer is called then -it should allocate those arrays when getbuffer is called and free them -when releasebuffer is called. +it should allocate those arrays when getbuffer is called (pointing to +them in the buffer-info structure provided) and free them when +releasebuffer is called. -The same bufferinfo struct should be used in the other buffer +The same bufferinfo struct should be used in the release-buffer interface call. The caller is responsible for the memory of the -bufferinfo object itself. +bufferinfo structure itself. ``typedef int (*releasebufferproc)(PyObject *obj, struct bufferinfo *view)`` Callers of getbufferproc must make sure that this function is @@ -285,9 +344,11 @@ calls have been made and shared. Either a single variable could be used to keep track of how many "views" have been exported, or a linked-list of bufferinfo structures filled in could be maintained in -each objet. All that is needed is to ensure that any memory shared -through the bufferinfo structure remains valid until releasebuffer is -called on that memory. +each object. + +All that is specifically required by the exporter, however, is to +ensure that any memory shared through the bufferinfo structure remains +valid until releasebuffer is called on the bufferinfo structure. New C-API calls are proposed @@ -301,7 +362,25 @@ :: - PyObject *PyObject_GetBuffer(PyObject *obj) + int PyObject_GetBuffer(PyObject *obj, struct bufferinfo *view, int flags) + +This is a C-API version of the getbuffer function call. It checks to +make sure object has the required function pointer and issues the +call. Returns -1 and raises an error on failure and returns 0 on +success. + +:: + + int PyObject_ReleaseBuffer(PyObject *obj, struct bufferinfo *view) + +This is a C-API version of the releasebuffer function call. It checks to +make sure the object has the required function pointer and issues the call. Returns 0 +on success and -1 (with an error raised) on failure. This function always +succeeds if there is no releasebuffer function for the object. + +:: + + PyObject *PyObject_GetMemoryView(PyObject *obj) Return a memory-view object from an object that defines the buffer interface. If make_ro is non-zero then request that the memory is made read-only until @@ -320,9 +399,9 @@ This is very similar to the current buffer object except offset has been removed because ptr can just be modified by offset and a single -offset is not sufficient. Also the hash has been removed because -using the buffer object as a hash even if it is read-only is rarely -useful. +offset is not sufficient for the sub-offsets. Also the hash has been +removed because using the buffer object as a hash even if it is +read-only is rarely useful. Also, the format, ndims, shape, strides, and suboffsets have been added. These additions will allow multi-dimensional slicing of the @@ -338,10 +417,10 @@ format and therefore does not need to keep track of how many views it has exported. -It exports a view using the base object. It releases a view by releasing -the view on the base object. Because, it will never re-allocate memory, -it does not need to keep track of how many it has exported but simple -reference counting will suffice. +It exports a view using the base object. It releases a view by +releasing the view on the base object. Because, it will never +re-allocate memory, it does not need to keep track of how many it has +exported but simple reference counting will suffice. :: @@ -363,7 +442,8 @@ fortran is 1, the first dimension of the underlying array will vary the fastest in the buffer. If fortran is 0, then the last dimension will vary the fastest (C-style contiguous). If fortran is -1, then it -does not matter and you will get whatever the object decides is easiest. +does not matter and you will get whatever the object decides is more +efficient. :: @@ -378,8 +458,8 @@ will be copied into the array in Fortran-style (first dimension varies the fastest). If fortran is 0, then the data will be copied into the array in C-style (last dimension varies the fastest). If fortran is -1, then -it does not matter and the copy will be made in whatever way is -easiest. +it does not matter and the copy will be made in whatever way is more +efficient. The last two C-API calls allow a standard way of getting data in and out of Python objects into contiguous memory areas no matter how it is @@ -388,20 +468,29 @@ :: - int PyObject_IsContiguous(struct bufferinfo *view); + int PyObject_IsContiguous(struct bufferinfo *view, int fortran); -Return 1 if the memory defined by the view object is C-style -contiguous. Return 0 otherwise. +Return 1 if the memory defined by the view object is C-style (fortran = 0) +or Fortran-style (fortran = 1) contiguous. Return 0 otherwise. :: void PyObject_FillContiguousStrides(int *ndims, Py_ssize_t *shape, int itemsize, - Py_ssize_t *strides) + Py_ssize_t *strides, int fortran) -Fill the strides array with byte-strides of a contiguous array of the -given shape with the given number of bytes per element. +Fill the strides array with byte-strides of a contiguous (C-style if +fortran is 0 or Fortran-style if fortran is 1) array of the given +shape with the given number of bytes per element. + +:: + int PyObject_FillBufferInfo(struct bufferinfo *view, void *buf, Py_ssize_t len, + int readonly, int infoflags) + +Fills in a buffer-info structure correctly for an exporter that can only share +a contiguous chunk of memory of "unsigned bytes" of the given length. Returns 0 on success +and -1 (with raising an error) on error Additions to the struct string-syntax @@ -432,18 +521,18 @@ ':name:' optional name of the preceeding element 'X{}' pointer to a function (optional function signature inside {}) -' ' ignored (allow better readability) +' \n\t' ignored (allow better readability) -- this may already be true ================ =========== The struct module will be changed to understand these as well and return appropriate Python objects on unpacking. Un-packing a -long-double will return a decimal object. Unpacking 'u' or -'w' will return Python unicode. Unpacking a multi-dimensional -array will return a list of lists. Un-packing a pointer will -return a ctypes pointer object. Un-packing a bit will return a -Python Bool. Spaces in the struct-string syntax will be ignored. -Unpacking a named-object will return a Python class with attributes -having those names. +long-double will return a decimal object or a ctypes long-double. +Unpacking 'u' or 'w' will return Python unicode. Unpacking a +multi-dimensional array will return a list of lists. Un-packing a +pointer will return a ctypes pointer object. Un-packing a bit will +return a Python Bool. Spaces in the struct-string syntax will be +ignored. Unpacking a named-object will return a Python class with +attributes having those names. Endian-specification ('=','>','<') is also allowed inside the string so that it can change if needed. The previously-specified @@ -483,7 +572,13 @@ unsigned char cval; } sub; } - 'i:ival: T{H:sval: B:bval: B:cval:}:sub:' + """i:ival: + T{ + H:sval: + B:bval: + B:cval: + }:sub: + """ Nested array :: @@ -493,6 +588,7 @@ } 'i:ival: (16,4)d:data:' + Code to be affected =================== @@ -513,6 +609,10 @@ Issues and Details ================== +It is intended that this PEP will be back-ported to Python 2.6 by +adding the C-API and the two functions to the existing buffer +protocol. + The proposed locking mechanism relies entirely on the exporter object to not invalidate any of the memory pointed to by the buffer structure until a corresponding releasebuffer is called. If it wants to be able @@ -527,7 +627,7 @@ because strided memory is very common when interfacing with compute libraries. -Also with this approach it should be possible to write generic code +Also, with this approach it should be possible to write generic code that works with both kinds of memory. Memory management of the format string, the shape array, the strides @@ -535,6 +635,20 @@ the responsibility of the exporting object. The consumer should not set these pointers to any other memory or try to free them. +Several ideas were discussed and rejected: + + Having a "releaser" object whose release-buffer was called. This + was deemed unacceptable because it caused the protocol to be + asymmetric (you called release on something different than you + "got" the buffer from). It also complicated the protocol without + providing a real benefit. + + Passing all the struct variables separately into the function. + This had the advantage that it allowed one to set NULL to + variables that were not of interest, but it also made the function + call more difficult. The flags variable allows the same + ability of consumers to be "simple" in how they call the protocol. + Code ======== @@ -542,6 +656,8 @@ this proposal but will welcome any help. + + Examples ========= @@ -572,7 +688,7 @@ So what does ImageObject's getbuffer do? Leaving error checking out:: - int Image_getbuffer(PyObject *self, struct bufferinfo *view) { + int Image_getbuffer(PyObject *self, struct bufferinfo *view, int flags) { static Py_ssize_t suboffsets[2] = { -1, 0 }; @@ -600,6 +716,58 @@ } +Ex. 2 +----------- + +This example shows how an object that wants to expose a contiguous +chunk of memory (which will never be re-allocated while the object is +alive) would do that.:: + + int myobject_getbuffer(PyObject *self, struct bufferinfo *view, int flags) { + + void *buf; + Py_ssize_t len; + int readonly=0; + + buf = /* Point to buffer */ + len = /* Set to size of buffer */ + readonly = /* Set to 1 if readonly */ + + return PyObject_FillBufferInfo(view, buf, len, readonly, flags); + } + + /* No releasebuffer is necessary because the memory will never + be re-allocated so the locking mechanism is not needed + */ + +Ex. 3 +----------- + +A consumer that wants to only get a simple contiguous chunk of bytes +from a Python object, obj would do the following:: + + + struct bufferinfo view; + int ret; + + if (PyObject_GetBuffer(obj, &view, Py_BUF_SIMPLE) < 0) { + /* error return */ + } + + /* Now, view.buf is the pointer to memory + view.len is the length + view.readonly is whether or not the memory is read-only. + */ + + + /* After using the information and you don't need it anymore */ + + if (PyObject_ReleaseBuffer(obj, &view) < 0) { + /* error return */ + } + + + Copyright ========= From python-checkins at python.org Tue Apr 10 14:58:49 2007 From: python-checkins at python.org (facundo.batista) Date: Tue, 10 Apr 2007 14:58:49 +0200 (CEST) Subject: [Python-checkins] r54732 - python/trunk/Lib/decimal.py Message-ID: <20070410125849.EB6091E400D@bag.python.org> Author: facundo.batista Date: Tue Apr 10 14:58:45 2007 New Revision: 54732 Modified: python/trunk/Lib/decimal.py Log: General clean-up. Lot of margin corrections, comments, some typos. Exceptions now are raised in the new style. And a mockup class is now also new style. Thanks Santiago Pereson. Modified: python/trunk/Lib/decimal.py ============================================================================== --- python/trunk/Lib/decimal.py (original) +++ python/trunk/Lib/decimal.py Tue Apr 10 14:58:45 2007 @@ -29,8 +29,8 @@ Decimal floating point has finite precision with arbitrarily large bounds. -The purpose of the module is to support arithmetic using familiar -"schoolhouse" rules and to avoid the some of tricky representation +The purpose of this module is to support arithmetic using familiar +"schoolhouse" rules and to avoid some of the tricky representation issues associated with binary floating point. The package is especially useful for financial applications or for contexts where users have expectations that are at odds with binary floating point (for instance, @@ -136,7 +136,7 @@ import copy as _copy -#Rounding +# Rounding ROUND_DOWN = 'ROUND_DOWN' ROUND_HALF_UP = 'ROUND_HALF_UP' ROUND_HALF_EVEN = 'ROUND_HALF_EVEN' @@ -145,11 +145,11 @@ ROUND_UP = 'ROUND_UP' ROUND_HALF_DOWN = 'ROUND_HALF_DOWN' -#Rounding decision (not part of the public API) +# Rounding decision (not part of the public API) NEVER_ROUND = 'NEVER_ROUND' # Round in division (non-divmod), sqrt ONLY ALWAYS_ROUND = 'ALWAYS_ROUND' # Every operation rounds at end. -#Errors +# Errors class DecimalException(ArithmeticError): """Base exception class. @@ -179,9 +179,9 @@ This occurs and signals clamped if the exponent of a result has been altered in order to fit the constraints of a specific concrete - representation. This may occur when the exponent of a zero result would - be outside the bounds of a representation, or when a large normal - number would have an encoded exponent that cannot be represented. In + representation. This may occur when the exponent of a zero result would + be outside the bounds of a representation, or when a large normal + number would have an encoded exponent that cannot be represented. In this latter case, the exponent is reduced to fit and the corresponding number of zero digits are appended to the coefficient ("fold-down"). """ @@ -194,8 +194,8 @@ Something creates a signaling NaN -INF + INF - 0 * (+-)INF - (+-)INF / (+-)INF + 0 * (+-)INF + (+-)INF / (+-)INF x % 0 (+-)INF % x x._rescale( non-integer ) @@ -207,7 +207,7 @@ """ def handle(self, context, *args): if args: - if args[0] == 1: #sNaN, must drop 's' but keep diagnostics + if args[0] == 1: # sNaN, must drop 's' but keep diagnostics return Decimal( (args[1]._sign, args[1]._int, 'n') ) return NaN @@ -216,11 +216,11 @@ This occurs and signals invalid-operation if an string is being converted to a number and it does not conform to the numeric string - syntax. The result is [0,qNaN]. + syntax. The result is [0,qNaN]. """ def handle(self, context, *args): - return (0, (0,), 'n') #Passed to something which uses a tuple. + return (0, (0,), 'n') # Passed to something which uses a tuple. class DivisionByZero(DecimalException, ZeroDivisionError): """Division by 0. @@ -245,7 +245,7 @@ This occurs and signals invalid-operation if the integer result of a divide-integer or remainder operation had too many digits (would be - longer than precision). The result is [0,qNaN]. + longer than precision). The result is [0,qNaN]. """ def handle(self, context, *args): @@ -256,12 +256,12 @@ This occurs and signals invalid-operation if division by zero was attempted (during a divide-integer, divide, or remainder operation), and - the dividend is also zero. The result is [0,qNaN]. + the dividend is also zero. The result is [0,qNaN]. """ def handle(self, context, tup=None, *args): if tup is not None: - return (NaN, NaN) #for 0 %0, 0 // 0 + return (NaN, NaN) # for 0 %0, 0 // 0 return NaN class Inexact(DecimalException): @@ -269,7 +269,7 @@ This occurs and signals inexact whenever the result of an operation is not exact (that is, it needed to be rounded and any discarded digits - were non-zero), or if an overflow or underflow condition occurs. The + were non-zero), or if an overflow or underflow condition occurs. The result in all cases is unchanged. The inexact signal may be tested (or trapped) to determine if a given @@ -281,11 +281,11 @@ """Invalid context. Unknown rounding, for example. This occurs and signals invalid-operation if an invalid context was - detected during an operation. This can occur if contexts are not checked + detected during an operation. This can occur if contexts are not checked on creation and either the precision exceeds the capability of the underlying concrete representation or an unknown or unsupported rounding - was specified. These aspects of the context need only be checked when - the values are required to be used. The result is [0,qNaN]. + was specified. These aspects of the context need only be checked when + the values are required to be used. The result is [0,qNaN]. """ def handle(self, context, *args): @@ -296,7 +296,7 @@ This occurs and signals rounded whenever the result of an operation is rounded (that is, some zero or non-zero digits were discarded from the - coefficient), or if an overflow or underflow condition occurs. The + coefficient), or if an overflow or underflow condition occurs. The result in all cases is unchanged. The rounded signal may be tested (or trapped) to determine if a given @@ -309,7 +309,7 @@ This occurs and signals subnormal whenever the result of a conversion or operation is subnormal (that is, its adjusted exponent is less than - Emin, before any rounding). The result in all cases is unchanged. + Emin, before any rounding). The result in all cases is unchanged. The subnormal signal may be tested (or trapped) to determine if a given or operation (or sequence of operations) yielded a subnormal result. @@ -328,13 +328,13 @@ For round-half-up and round-half-even (and for round-half-down and round-up, if implemented), the result of the operation is [sign,inf], - where sign is the sign of the intermediate result. For round-down, the + where sign is the sign of the intermediate result. For round-down, the result is the largest finite number that can be represented in the - current precision, with the sign of the intermediate result. For + current precision, with the sign of the intermediate result. For round-ceiling, the result is the same as for round-down if the sign of - the intermediate result is 1, or is [0,inf] otherwise. For round-floor, + the intermediate result is 1, or is [0,inf] otherwise. For round-floor, the result is the same as for round-down if the sign of the intermediate - result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded + result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded will also be raised. """ @@ -360,10 +360,10 @@ This occurs and signals underflow if a result is inexact and the adjusted exponent of the result would be smaller (more negative) than the smallest value that can be handled by the implementation (the value - Emin). That is, the result is both inexact and subnormal. + Emin). That is, the result is both inexact and subnormal. The result after an underflow will be a subnormal number rounded, if - necessary, so that its exponent is not less than Etiny. This may result + necessary, so that its exponent is not less than Etiny. This may result in 0 with the sign of the intermediate result and an exponent of Etiny. In all cases, Inexact, Rounded, and Subnormal will also be raised. @@ -379,7 +379,7 @@ DivisionUndefined:InvalidOperation, InvalidContext:InvalidOperation} -##### Context Functions ####################################### +##### Context Functions ################################################## # The getcontext() and setcontext() function manage access to a thread-local # current context. Py2.4 offers direct support for thread locals. If that @@ -392,7 +392,7 @@ except ImportError: # Python was compiled without threads; create a mock object instead import sys - class MockThreading: + class MockThreading(object): def local(self, sys=sys): return sys.modules[__name__] threading = MockThreading() @@ -403,8 +403,8 @@ except AttributeError: - #To fix reloading, force it to create a new context - #Old contexts have different exceptions in their dicts, making problems. + # To fix reloading, force it to create a new context + # Old contexts have different exceptions in their dicts, making problems. if hasattr(threading.currentThread(), '__decimal_context__'): del threading.currentThread().__decimal_context__ @@ -469,14 +469,14 @@ ctx.prec += 2 # Rest of sin calculation algorithm # uses a precision 2 greater than normal - return +s # Convert result to normal precision + return +s # Convert result to normal precision def sin(x): with localcontext(ExtendedContext): # Rest of sin calculation algorithm # uses the Extended Context from the # General Decimal Arithmetic Specification - return +s # Convert result to normal context + return +s # Convert result to normal context """ # The string below can't be included in the docstring until Python 2.6 @@ -502,7 +502,7 @@ return _ContextManager(ctx) -##### Decimal class ########################################### +##### Decimal class ####################################################### class Decimal(object): """Floating point class for decimal arithmetic.""" @@ -518,7 +518,7 @@ >>> Decimal('3.14') # string input Decimal("3.14") - >>> Decimal((0, (3, 1, 4), -2)) # tuple input (sign, digit_tuple, exponent) + >>> Decimal((0, (3, 1, 4), -2)) # tuple (sign, digit_tuple, exponent) Decimal("3.14") >>> Decimal(314) # int or long Decimal("314") @@ -557,13 +557,13 @@ # tuple/list conversion (possibly from as_tuple()) if isinstance(value, (list,tuple)): if len(value) != 3: - raise ValueError, 'Invalid arguments' + raise ValueError('Invalid arguments') if value[0] not in (0,1): - raise ValueError, 'Invalid sign' + raise ValueError('Invalid sign') for digit in value[1]: if not isinstance(digit, (int,long)) or digit < 0: - raise ValueError, "The second value in the tuple must be composed of non negative integer elements." - + raise ValueError("The second value in the tuple must be" + "composed of non negative integer elements.") self._sign = value[0] self._int = tuple(value[1]) if value[2] in ('F','n','N'): @@ -596,22 +596,23 @@ if _isnan(value): sig, sign, diag = _isnan(value) self._is_special = True - if len(diag) > context.prec: #Diagnostic info too long + if len(diag) > context.prec: # Diagnostic info too long self._sign, self._int, self._exp = \ context._raise_error(ConversionSyntax) return self if sig == 1: - self._exp = 'n' #qNaN - else: #sig == 2 - self._exp = 'N' #sNaN + self._exp = 'n' # qNaN + else: # sig == 2 + self._exp = 'N' # sNaN self._sign = sign - self._int = tuple(map(int, diag)) #Diagnostic info + self._int = tuple(map(int, diag)) # Diagnostic info return self try: self._sign, self._int, self._exp = _string2exact(value) except ValueError: self._is_special = True - self._sign, self._int, self._exp = context._raise_error(ConversionSyntax) + self._sign, self._int, self._exp = \ + context._raise_error(ConversionSyntax) return self raise TypeError("Cannot convert %r to Decimal" % value) @@ -694,15 +695,15 @@ if self._is_special or other._is_special: ans = self._check_nans(other, context) if ans: - return 1 # Comparison involving NaN's always reports self > other + return 1 # Comparison involving NaN's always reports self > other # INF = INF return cmp(self._isinfinity(), other._isinfinity()) if not self and not other: - return 0 #If both 0, sign comparison isn't certain. + return 0 # If both 0, sign comparison isn't certain. - #If different signs, neg one is less + # If different signs, neg one is less if other._sign < self._sign: return -1 if self._sign < other._sign: @@ -713,7 +714,7 @@ if self_adjusted == other_adjusted and \ self._int + (0,)*(self._exp - other._exp) == \ other._int + (0,)*(other._exp - self._exp): - return 0 #equal, except in precision. ([0]*(-x) = []) + return 0 # equal, except in precision. ([0]*(-x) = []) elif self_adjusted > other_adjusted and self._int[0] != 0: return (-1)**self._sign elif self_adjusted < other_adjusted and other._int[0] != 0: @@ -724,7 +725,7 @@ context = getcontext() context = context._shallow_copy() - rounding = context._set_rounding(ROUND_UP) #round away from 0 + rounding = context._set_rounding(ROUND_UP) # round away from 0 flags = context._ignore_all_flags() res = self.__sub__(other, context=context) @@ -762,7 +763,7 @@ if other is NotImplemented: return other - #compare(NaN, NaN) = NaN + # Compare(NaN, NaN) = NaN if (self._is_special or other and other._is_special): ans = self._check_nans(other, context) if ans: @@ -823,11 +824,11 @@ tmp = map(str, self._int) numdigits = len(self._int) leftdigits = self._exp + numdigits - if eng and not self: #self = 0eX wants 0[.0[0]]eY, not [[0]0]0eY - if self._exp < 0 and self._exp >= -6: #short, no need for e/E + if eng and not self: # self = 0eX wants 0[.0[0]]eY, not [[0]0]0eY + if self._exp < 0 and self._exp >= -6: # short, no need for e/E s = '-'*self._sign + '0.' + '0'*(abs(self._exp)) return s - #exp is closest mult. of 3 >= self._exp + # exp is closest mult. of 3 >= self._exp exp = ((self._exp - 1)// 3 + 1) * 3 if exp != self._exp: s = '0.'+'0'*(exp - self._exp) @@ -839,7 +840,7 @@ else: s += 'e' if exp > 0: - s += '+' #0.0e+3, not 0.0e3 + s += '+' # 0.0e+3, not 0.0e3 s += str(exp) s = '-'*self._sign + s return s @@ -979,19 +980,19 @@ return ans if self._isinfinity(): - #If both INF, same sign => same as both, opposite => error. + # If both INF, same sign => same as both, opposite => error. if self._sign != other._sign and other._isinfinity(): return context._raise_error(InvalidOperation, '-INF + INF') return Decimal(self) if other._isinfinity(): - return Decimal(other) #Can't both be infinity here + return Decimal(other) # Can't both be infinity here shouldround = context._rounding_decision == ALWAYS_ROUND exp = min(self._exp, other._exp) negativezero = 0 if context.rounding == ROUND_FLOOR and self._sign != other._sign: - #If the answer is 0, the sign should be negative, in this case. + # If the answer is 0, the sign should be negative, in this case. negativezero = 1 if not self and not other: @@ -1026,19 +1027,19 @@ return Decimal((negativezero, (0,), exp)) if op1.int < op2.int: op1, op2 = op2, op1 - #OK, now abs(op1) > abs(op2) + # OK, now abs(op1) > abs(op2) if op1.sign == 1: result.sign = 1 op1.sign, op2.sign = op2.sign, op1.sign else: result.sign = 0 - #So we know the sign, and op1 > 0. + # So we know the sign, and op1 > 0. elif op1.sign == 1: result.sign = 1 op1.sign, op2.sign = (0, 0) else: result.sign = 0 - #Now, op1 > abs(op2) > 0 + # Now, op1 > abs(op2) > 0 if op2.sign == 0: result.int = op1.int + op2.int @@ -1096,7 +1097,8 @@ if ans: return ans - return Decimal(self) # Must be infinite, and incrementing makes no difference + # Must be infinite, and incrementing makes no difference + return Decimal(self) L = list(self._int) L[-1] += 1 @@ -1152,7 +1154,7 @@ if not self or not other: ans = Decimal((resultsign, (0,), resultexp)) if shouldround: - #Fixing in case the exponent is out of bounds + # Fixing in case the exponent is out of bounds ans = ans._fix(context) return ans @@ -1171,7 +1173,7 @@ op1 = _WorkRep(self) op2 = _WorkRep(other) - ans = Decimal( (resultsign, map(int, str(op1.int * op2.int)), resultexp)) + ans = Decimal((resultsign, map(int, str(op1.int * op2.int)), resultexp)) if shouldround: ans = ans._fix(context) @@ -1264,12 +1266,11 @@ sign, 1) return context._raise_error(DivisionByZero, 'x / 0', sign) - #OK, so neither = 0, INF or NaN - + # OK, so neither = 0, INF or NaN shouldround = context._rounding_decision == ALWAYS_ROUND - #If we're dividing into ints, and self < other, stop. - #self.__abs__(0) does not round. + # If we're dividing into ints, and self < other, stop. + # self.__abs__(0) does not round. if divmod and (self.__abs__(0, context) < other.__abs__(0, context)): if divmod == 1 or divmod == 3: @@ -1281,7 +1282,7 @@ ans2) elif divmod == 2: - #Don't round the mod part, if we don't need it. + # Don't round the mod part, if we don't need it. return (Decimal( (sign, (0,), 0) ), Decimal(self)) op1 = _WorkRep(self) @@ -1330,7 +1331,7 @@ op1.exp -= 1 if res.exp == 0 and divmod and op2.int > op1.int: - #Solves an error in precision. Same as a previous block. + # Solves an error in precision. Same as a previous block. if res.int >= prec_limit and shouldround: return context._raise_error(DivisionImpossible) @@ -1416,7 +1417,7 @@ # ignored in the calling function. context = context._shallow_copy() flags = context._ignore_flags(Rounded, Inexact) - #keep DivisionImpossible flags + # Keep DivisionImpossible flags (side, r) = self.__divmod__(other, context=context) if r._isnan(): @@ -1439,7 +1440,7 @@ if r < comparison: r._sign, comparison._sign = s1, s2 - #Get flags now + # Get flags now self.__divmod__(other, context=context) return r._fix(context) r._sign, comparison._sign = s1, s2 @@ -1461,7 +1462,8 @@ if r > comparison or decrease and r == comparison: r._sign, comparison._sign = s1, s2 context.prec += 1 - if len(side.__add__(Decimal(1), context=context)._int) >= context.prec: + numbsquant = len(side.__add__(Decimal(1), context=context)._int) + if numbsquant >= context.prec: context.prec -= 1 return context._raise_error(DivisionImpossible)[1] context.prec -= 1 @@ -1496,7 +1498,7 @@ context = getcontext() return context._raise_error(InvalidContext) elif self._isinfinity(): - raise OverflowError, "Cannot convert infinity to long" + raise OverflowError("Cannot convert infinity to long") if self._exp >= 0: s = ''.join(map(str, self._int)) + '0'*self._exp else: @@ -1550,13 +1552,13 @@ context._raise_error(Clamped) return ans ans = ans._rescale(Etiny, context=context) - #It isn't zero, and exp < Emin => subnormal + # It isn't zero, and exp < Emin => subnormal context._raise_error(Subnormal) if context.flags[Inexact]: context._raise_error(Underflow) else: if ans: - #Only raise subnormal if non-zero. + # Only raise subnormal if non-zero. context._raise_error(Subnormal) else: Etop = context.Etop() @@ -1573,7 +1575,8 @@ return ans context._raise_error(Inexact) context._raise_error(Rounded) - return context._raise_error(Overflow, 'above Emax', ans._sign) + c = context._raise_error(Overflow, 'above Emax', ans._sign) + return c return ans def _round(self, prec=None, rounding=None, context=None): @@ -1633,18 +1636,18 @@ ans = Decimal( (temp._sign, tmp, temp._exp - expdiff)) return ans - #OK, but maybe all the lost digits are 0. + # OK, but maybe all the lost digits are 0. lostdigits = self._int[expdiff:] if lostdigits == (0,) * len(lostdigits): ans = Decimal( (temp._sign, temp._int[:prec], temp._exp - expdiff)) - #Rounded, but not Inexact + # Rounded, but not Inexact context._raise_error(Rounded) return ans # Okay, let's round and lose data this_function = getattr(temp, self._pick_rounding_function[rounding]) - #Now we've got the rounding function + # Now we've got the rounding function if prec != context.prec: context = context._shallow_copy() @@ -1740,7 +1743,7 @@ context = getcontext() if self._is_special or n._is_special or n.adjusted() > 8: - #Because the spot << doesn't work with really big exponents + # Because the spot << doesn't work with really big exponents if n._isinfinity() or n.adjusted() > 8: return context._raise_error(InvalidOperation, 'x ** INF') @@ -1770,9 +1773,10 @@ return Infsign[sign] return Decimal( (sign, (0,), 0) ) - #with ludicrously large exponent, just raise an overflow and return inf. - if not modulo and n > 0 and (self._exp + len(self._int) - 1) * n > context.Emax \ - and self: + # With ludicrously large exponent, just raise an overflow + # and return inf. + if not modulo and n > 0 and \ + (self._exp + len(self._int) - 1) * n > context.Emax and self: tmp = Decimal('inf') tmp._sign = sign @@ -1792,7 +1796,7 @@ context = context._shallow_copy() context.prec = firstprec + elength + 1 if n < 0: - #n is a long now, not Decimal instance + # n is a long now, not Decimal instance n = -n mul = Decimal(1).__div__(mul, context=context) @@ -1801,7 +1805,7 @@ spot <<= 1 spot >>= 1 - #Spot is the highest power of 2 less than n + # spot is the highest power of 2 less than n while spot: val = val.__mul__(val, context=context) if val._isinfinity(): @@ -1859,7 +1863,7 @@ if exp._isinfinity() or self._isinfinity(): if exp._isinfinity() and self._isinfinity(): - return self #if both are inf, it is OK + return self # if both are inf, it is OK if context is None: context = getcontext() return context._raise_error(InvalidOperation, @@ -1963,13 +1967,13 @@ return Decimal(self) if not self: - #exponent = self._exp / 2, using round_down. - #if self._exp < 0: + # exponent = self._exp / 2, using round_down. + # if self._exp < 0: # exp = (self._exp+1) // 2 - #else: + # else: exp = (self._exp) // 2 if self._sign == 1: - #sqrt(-0) = -0 + # sqrt(-0) = -0 return Decimal( (1, (0,), exp)) else: return Decimal( (0, (0,), exp)) @@ -2004,8 +2008,7 @@ context=context), context=context) ans._exp -= 1 + tmp.adjusted() // 2 - #ans is now a linear approximation. - + # ans is now a linear approximation. Emax, Emin = context.Emax, context.Emin context.Emax, context.Emin = DefaultContext.Emax, DefaultContext.Emin @@ -2020,12 +2023,12 @@ if context.prec == maxp: break - #round to the answer's precision-- the only error can be 1 ulp. + # Round to the answer's precision-- the only error can be 1 ulp. context.prec = firstprec prevexp = ans.adjusted() ans = ans._round(context=context) - #Now, check if the other last digits are better. + # Now, check if the other last digits are better. context.prec = firstprec + 1 # In case we rounded up another digit and we should actually go lower. if prevexp != ans.adjusted(): @@ -2057,10 +2060,10 @@ context._raise_error(Rounded) context._raise_error(Inexact) else: - #Exact answer, so let's set the exponent right. - #if self._exp < 0: + # Exact answer, so let's set the exponent right. + # if self._exp < 0: # exp = (self._exp +1)// 2 - #else: + # else: exp = self._exp // 2 context.prec += ans._exp - exp ans = ans._rescale(exp, context=context) @@ -2081,7 +2084,7 @@ return other if self._is_special or other._is_special: - # if one operand is a quiet NaN and the other is number, then the + # If one operand is a quiet NaN and the other is number, then the # number is always returned sn = self._isnan() on = other._isnan() @@ -2095,13 +2098,13 @@ ans = self c = self.__cmp__(other) if c == 0: - # if both operands are finite and equal in numerical value + # If both operands are finite and equal in numerical value # then an ordering is applied: # - # if the signs differ then max returns the operand with the + # If the signs differ then max returns the operand with the # positive sign and min returns the operand with the negative sign # - # if the signs are the same then the exponent is used to select + # If the signs are the same then the exponent is used to select # the result. if self._sign != other._sign: if self._sign: @@ -2122,7 +2125,7 @@ def min(self, other, context=None): """Returns the smaller value. - like min(self, other) except if one is not a number, returns + Like min(self, other) except if one is not a number, returns NaN (and signals if one is sNaN). Also rounds. """ other = _convert_other(other) @@ -2130,7 +2133,7 @@ return other if self._is_special or other._is_special: - # if one operand is a quiet NaN and the other is number, then the + # If one operand is a quiet NaN and the other is number, then the # number is always returned sn = self._isnan() on = other._isnan() @@ -2144,13 +2147,13 @@ ans = self c = self.__cmp__(other) if c == 0: - # if both operands are finite and equal in numerical value + # If both operands are finite and equal in numerical value # then an ordering is applied: # - # if the signs differ then max returns the operand with the + # If the signs differ then max returns the operand with the # positive sign and min returns the operand with the negative sign # - # if the signs are the same then the exponent is used to select + # If the signs are the same then the exponent is used to select # the result. if self._sign != other._sign: if other._sign: @@ -2185,11 +2188,11 @@ """Return the adjusted exponent of self""" try: return self._exp + len(self._int) - 1 - #If NaN or Infinity, self._exp is string + # If NaN or Infinity, self._exp is string except TypeError: return 0 - # support for pickling, copy, and deepcopy + # Support for pickling, copy, and deepcopy def __reduce__(self): return (self.__class__, (str(self),)) @@ -2203,13 +2206,14 @@ return self # My components are also immutable return self.__class__(str(self)) -##### Context class ########################################### +##### Context class ####################################################### # get rounding method function: -rounding_functions = [name for name in Decimal.__dict__.keys() if name.startswith('_round_')] +rounding_functions = [name for name in Decimal.__dict__.keys() + if name.startswith('_round_')] for name in rounding_functions: - #name is like _round_half_even, goes to the global ROUND_HALF_EVEN value. + # name is like _round_half_even, goes to the global ROUND_HALF_EVEN value. globalname = name[1:].upper() val = globals()[globalname] Decimal._pick_rounding_function[val] = name @@ -2236,7 +2240,7 @@ Contains: prec - precision (for use in rounding, division, square roots..) - rounding - rounding type. (how you round) + rounding - rounding type (how you round) _rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do you round? traps - If traps[exception] = 1, then the exception is raised when it is caused. Otherwise, a value is @@ -2277,9 +2281,13 @@ def __repr__(self): """Show the current context.""" s = [] - s.append('Context(prec=%(prec)d, rounding=%(rounding)s, Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d' % vars(self)) - s.append('flags=[' + ', '.join([f.__name__ for f, v in self.flags.items() if v]) + ']') - s.append('traps=[' + ', '.join([t.__name__ for t, v in self.traps.items() if v]) + ']') + s.append('Context(prec=%(prec)d, rounding=%(rounding)s, ' + 'Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d' + % vars(self)) + names = [f.__name__ for f, v in self.flags.items() if v] + s.append('flags=[' + ', '.join(names) + ']') + names = [t.__name__ for t, v in self.traps.items() if v] + s.append('traps=[' + ', '.join(names) + ']') return ', '.join(s) + ')' def clear_flags(self): @@ -2296,9 +2304,9 @@ def copy(self): """Returns a deep copy from self.""" - nc = Context(self.prec, self.rounding, self.traps.copy(), self.flags.copy(), - self._rounding_decision, self.Emin, self.Emax, - self.capitals, self._clamp, self._ignored_flags) + nc = Context(self.prec, self.rounding, self.traps.copy(), + self.flags.copy(), self._rounding_decision, self.Emin, + self.Emax, self.capitals, self._clamp, self._ignored_flags) return nc __copy__ = copy @@ -2312,16 +2320,16 @@ """ error = _condition_map.get(condition, condition) if error in self._ignored_flags: - #Don't touch the flag + # Don't touch the flag return error().handle(self, *args) self.flags[error] += 1 if not self.traps[error]: - #The errors define how to handle themselves. + # The errors define how to handle themselves. return condition().handle(self, *args) # Errors should only be risked on copies of the context - #self._ignored_flags = [] + # self._ignored_flags = [] raise error, explanation def _ignore_all_flags(self): @@ -2345,7 +2353,7 @@ def __hash__(self): """A Context cannot be hashed.""" # We inherit object.__hash__, so we must deny this explicitly - raise TypeError, "Cannot hash a Context." + raise TypeError("Cannot hash a Context.") def Etiny(self): """Returns Etiny (= Emin - prec + 1)""" @@ -2400,12 +2408,12 @@ d = Decimal(num, context=self) return d._fix(self) - #Methods + # Methods def abs(self, a): """Returns the absolute value of the operand. If the operand is negative, the result is the same as using the minus - operation on the operand. Otherwise, the result is the same as using + operation on the operand. Otherwise, the result is the same as using the plus operation on the operand. >>> ExtendedContext.abs(Decimal('2.1')) @@ -2507,8 +2515,8 @@ If either operand is a NaN then the general rules apply. Otherwise, the operands are compared as as though by the compare - operation. If they are numerically equal then the left-hand operand - is chosen as the result. Otherwise the maximum (closer to positive + operation. If they are numerically equal then the left-hand operand + is chosen as the result. Otherwise the maximum (closer to positive infinity) of the two operands is chosen as the result. >>> ExtendedContext.max(Decimal('3'), Decimal('2')) @@ -2527,8 +2535,8 @@ If either operand is a NaN then the general rules apply. Otherwise, the operands are compared as as though by the compare - operation. If they are numerically equal then the left-hand operand - is chosen as the result. Otherwise the minimum (closer to negative + operation. If they are numerically equal then the left-hand operand + is chosen as the result. Otherwise the minimum (closer to negative infinity) of the two operands is chosen as the result. >>> ExtendedContext.min(Decimal('3'), Decimal('2')) @@ -2617,14 +2625,14 @@ The right-hand operand must be a whole number whose integer part (after any exponent has been applied) has no more than 9 digits and whose - fractional part (if any) is all zeros before any rounding. The operand + fractional part (if any) is all zeros before any rounding. The operand may be positive, negative, or zero; if negative, the absolute value of the power is used, and the left-hand operand is inverted (divided into 1) before use. If the increased precision needed for the intermediate calculations - exceeds the capabilities of the implementation then an Invalid operation - condition is raised. + exceeds the capabilities of the implementation then an Invalid + operation condition is raised. If, when raising to a negative power, an underflow occurs during the division into 1, the operation is not halted at that point but @@ -2662,18 +2670,18 @@ return a.__pow__(b, modulo, context=self) def quantize(self, a, b): - """Returns a value equal to 'a' (rounded) and having the exponent of 'b'. + """Returns a value equal to 'a' (rounded), having the exponent of 'b'. The coefficient of the result is derived from that of the left-hand - operand. It may be rounded using the current rounding setting (if the + operand. It may be rounded using the current rounding setting (if the exponent is being increased), multiplied by a positive power of ten (if the exponent is being decreased), or is unchanged (if the exponent is already equal to that of the right-hand operand). Unlike other operations, if the length of the coefficient after the quantize operation would be greater than precision then an Invalid - operation condition is raised. This guarantees that, unless there is an - error condition, the exponent of the result of a quantize is always + operation condition is raised. This guarantees that, unless there is + an error condition, the exponent of the result of a quantize is always equal to that of the right-hand operand. Also unlike other operations, quantize will never raise Underflow, even @@ -2716,9 +2724,9 @@ """Returns the remainder from integer division. The result is the residue of the dividend after the operation of - calculating integer division as described for divide-integer, rounded to - precision digits if necessary. The sign of the result, if non-zero, is - the same as that of the original dividend. + calculating integer division as described for divide-integer, rounded + to precision digits if necessary. The sign of the result, if + non-zero, is the same as that of the original dividend. This operation will fail under the same conditions as integer division (that is, if integer division on the same two operands would fail, the @@ -2742,7 +2750,7 @@ def remainder_near(self, a, b): """Returns to be "a - b * n", where n is the integer nearest the exact value of "x / b" (if two integers are equally near then the even one - is chosen). If the result is equal to 0 then its sign will be the + is chosen). If the result is equal to 0 then its sign will be the sign of a. This operation will fail under the same conditions as integer division @@ -2784,7 +2792,7 @@ return a.same_quantum(b) def sqrt(self, a): - """Returns the square root of a non-negative number to context precision. + """Square root of a non-negative number to context precision. If the result must be inexact, it is rounded using the round-half-even algorithm. @@ -2845,7 +2853,7 @@ as using the quantize() operation using the given operand as the left-hand-operand, 1E+0 as the right-hand-operand, and the precision of the operand as the precision setting, except that no flags will - be set. The rounding mode is taken from the context. + be set. The rounding mode is taken from the context. >>> ExtendedContext.to_integral(Decimal('2.1')) Decimal("2") @@ -2920,8 +2928,9 @@ other_len = len(str(other.int)) if numdigits > (other_len + prec + 1 - tmp_len): # If the difference in adjusted exps is > prec+1, we know - # other is insignificant, so might as well put a 1 after the precision. - # (since this is only for addition.) Also stops use of massive longs. + # other is insignificant, so might as well put a 1 after the + # precision (since this is only for addition). Also stops + # use of massive longs. extend = prec + 2 - tmp_len if extend <= 0: @@ -2944,13 +2953,13 @@ Used on _WorkRep instances during division. """ adjust = 0 - #If op1 is smaller, make it larger + # If op1 is smaller, make it larger while op2.int > op1.int: op1.int *= 10 op1.exp -= 1 adjust += 1 - #If op2 is too small, make it larger + # If op2 is too small, make it larger while op1.int >= (10 * op2.int): op2.int *= 10 op2.exp -= 1 @@ -2958,7 +2967,7 @@ return op1, op2, adjust -##### Helper Functions ######################################## +##### Helper Functions #################################################### def _convert_other(other): """Convert other to Decimal. @@ -2999,16 +3008,16 @@ if not num: return 0 - #get the sign, get rid of trailing [+-] + # Get the sign, get rid of trailing [+-] sign = 0 if num[0] == '+': num = num[1:] - elif num[0] == '-': #elif avoids '+-nan' + elif num[0] == '-': # elif avoids '+-nan' num = num[1:] sign = 1 if num.startswith('nan'): - if len(num) > 3 and not num[3:].isdigit(): #diagnostic info + if len(num) > 3 and not num[3:].isdigit(): # diagnostic info return 0 return (1, sign, num[3:].lstrip('0')) if num.startswith('snan'): @@ -3018,7 +3027,7 @@ return 0 -##### Setup Specific Contexts ################################ +##### Setup Specific Contexts ############################################ # The default context prototype used by Context() # Is mutable, so that new contexts can have different default values @@ -3051,19 +3060,19 @@ ) -##### Useful Constants (internal use only) #################### +##### Useful Constants (internal use only) ################################ -#Reusable defaults +# Reusable defaults Inf = Decimal('Inf') negInf = Decimal('-Inf') -#Infsign[sign] is infinity w/ that sign +# Infsign[sign] is infinity w/ that sign Infsign = (Inf, negInf) NaN = Decimal('NaN') -##### crud for parsing strings ################################# +##### crud for parsing strings ############################################# import re # There's an optional sign at the start, and an optional exponent @@ -3083,13 +3092,15 @@ ([eE](?P[-+]? \d+))? # \s* $ -""", re.VERBOSE).match #Uncomment the \s* to allow leading or trailing spaces. +""", re.VERBOSE).match # Uncomment the \s* to allow leading or trailing spaces. del re -# return sign, n, p s.t. float string value == -1**sign * n * 10**p exactly - def _string2exact(s): + """Return sign, n, p s.t. + + Float string value == -1**sign * n * 10**p exactly + """ m = _parser(s) if m is None: raise ValueError("invalid literal for Decimal: %r" % s) From python at rcn.com Tue Apr 10 18:03:00 2007 From: python at rcn.com (Raymond Hettinger) Date: Tue, 10 Apr 2007 12:03:00 -0400 (EDT) Subject: [Python-checkins] r54732 - python/trunk/Lib/decimal.py Message-ID: <20070410120300.BEU16324@ms09.lnh.mail.rcn.net> I don't think patches like this are a good idea. For almost zero benefit, we've lost the clean info in "svn ann" and lost having the code in Py2.6 exactly match Py2.5 and Py2.4 (so it will now be more difficult to backport and validate real bug fixes). When the exceptions were changed to new-style, I hope there was a speed-up, that there is no change in semantics, and that the code still runs under Py2.3 as promised in the header. Raymond ----------------------------------------------------------------- Modified: python/trunk/Lib/decimal.py Log: General clean-up. Lot of margin corrections, comments, some typos. Exceptions now are raised in the new style. And a mockup class is now also new style. Thanks Santiago Pereson. From facundobatista at gmail.com Tue Apr 10 19:31:53 2007 From: facundobatista at gmail.com (Facundo Batista) Date: Tue, 10 Apr 2007 14:31:53 -0300 Subject: [Python-checkins] r54732 - python/trunk/Lib/decimal.py In-Reply-To: <20070410120300.BEU16324@ms09.lnh.mail.rcn.net> References: <20070410120300.BEU16324@ms09.lnh.mail.rcn.net> Message-ID: 2007/4/10, Raymond Hettinger : > I don't think patches like this are a good idea. For almost > zero benefit, we've lost the clean info in "svn ann" and lost > having the code in Py2.6 exactly match Py2.5 and Py2.4 > (so it will now be more difficult to backport and validate > real bug fixes). Well. This is the first step in "me started working on decimal again". The Decimal spec changed: it has new operations, but also changed the behaviour of some already-present operations (right now I'm pulling my hair because of a corner case of rounding that must behave different in quantize). What I don't know is: these changes will be considered as "bugs" and backported to <2.6, or it will be considered as little changes that will join the bigger changes in 2.6? If the former, I agree with you that this change should be reversed (note that I didn't realize these losses at its moment, but everybody learns, ;). What do you think? > When the exceptions were changed to new-style, I hope there > was a speed-up, that there is no change in semantics, and > that the code still runs under Py2.3 as promised in the header. It changed from "ValueError, 'foo'" to "ValueError('foo')". Don't remember when this was introduced in the language, though (didn't find it overlooking the "What's new" docs...). Thank you! -- . Facundo Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org/ar/ From python-checkins at python.org Tue Apr 10 19:44:36 2007 From: python-checkins at python.org (brett.cannon) Date: Tue, 10 Apr 2007 19:44:36 +0200 (CEST) Subject: [Python-checkins] r54734 - sandbox/trunk/import_in_py/import_diagram.dot sandbox/trunk/import_in_py/import_diagram.svg Message-ID: <20070410174436.799101E400F@bag.python.org> Author: brett.cannon Date: Tue Apr 10 19:44:33 2007 New Revision: 54734 Added: sandbox/trunk/import_in_py/import_diagram.dot (contents, props changed) sandbox/trunk/import_in_py/import_diagram.svg (contents, props changed) Log: Add a Graphviz DOT file and the corresponding SVG file that diagrams the control flow of import. Added: sandbox/trunk/import_in_py/import_diagram.dot ============================================================================== --- (empty file) +++ sandbox/trunk/import_in_py/import_diagram.dot Tue Apr 10 19:44:33 2007 @@ -0,0 +1,72 @@ +/* XXX For inputs to a function, can use dashed or dotted lines; that way solid + * lines are just for control flow. */ +digraph Import { + compound=true; + + /* Input. */ + subgraph cluster_input { + label="Input"; + color=blue; + node [shape=ellipse]; + + module_name [width=2]; + globals [width=1.5]; + locals [width=1.5]; + fromlist [width=1.5]; + level [width=1.5]; + } + + /* Output. */ + subgraph cluster_output { + label="Output"; + color=blue; + node [shape=ellipse]; + + return [width=1.5]; + ImportError [width=2]; + } + + /* All work that occurs while the import lock is held. */ + subgraph cluster_import_locking { + label="Import Lock Held"; + color=blue; + + /* Name resolution needed? */ + if_name_resolution [shape=diamond, + label="level != 0 and \n '__name__'", + width=3, height=1.5]; + + /* Name resolution cluster. */ + subgraph cluster_name_resolution { + label="Make name absolute"; + color=blue; + + pkg_level_adjust [shape=box, + label="level - 1 \n if '__path__' \n else level", + width=2, height=1]; + + test_depth [shape=diamond, label="Depth < level", + width=2.5]; + + adjust_name [shape=box, label="Adjust name", width=1.75]; + + pkg_level_adjust -> test_depth; + test_depth -> ImportError [label="True"]; + test_depth -> adjust_name [label="False"]; + } + if_name_resolution -> pkg_level_adjust [label="True"]; + + /* Name is absolute. */ + abs_module_name [shape=point, label="absolute \n module name"]; + + adjust_name -> abs_module_name; + if_name_resolution -> abs_module_name [label="False"]; + + abs_module_name -> return; + } + + /* XXX until I decide how I want to handle the inputs. */ + start [shape=point]; + {module_name; globals; locals; fromlist; level} -> start; + start-> if_name_resolution; +} Added: sandbox/trunk/import_in_py/import_diagram.svg ============================================================================== --- (empty file) +++ sandbox/trunk/import_in_py/import_diagram.svg Tue Apr 10 19:44:33 2007 @@ -0,0 +1,137 @@ + + + + + +Import +cluster_input + +Input + +cluster_output + +Output + +cluster_import_locking + +Import Lock Held + +cluster_name_resolution + +Make name absolute + +module_name + +module_name + +start + + +module_name->start + + + +globals + +globals + +globals->start + + + +locals + +locals + +locals->start + + + +fromlist + +fromlist + +fromlist->start + + + +level + +level + +level->start + + + +return + +return + +ImportError + +ImportError + +if_name_resolution + +level != 0 and + '__name__' + +pkg_level_adjust + +level - 1 + if '__path__' + else level + +if_name_resolution->pkg_level_adjust + + +True + +abs_module_name + + +if_name_resolution->abs_module_name + + +False + +test_depth + +Depth < level + +pkg_level_adjust->test_depth + + + +test_depth->ImportError + + +True + +adjust_name + +Adjust name + +test_depth->adjust_name + + +False + +adjust_name->abs_module_name + + + +abs_module_name->return + + + +start->if_name_resolution + + + + + From python-checkins at python.org Tue Apr 10 20:38:00 2007 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 10 Apr 2007 20:38:00 +0200 (CEST) Subject: [Python-checkins] r54735 - peps/trunk/pep-3116.txt Message-ID: <20070410183800.B71C21E400D@bag.python.org> Author: guido.van.rossum Date: Tue Apr 10 20:37:53 2007 New Revision: 54735 Modified: peps/trunk/pep-3116.txt Log: seek() returns an int everywhere. Modified: peps/trunk/pep-3116.txt ============================================================================== --- peps/trunk/pep-3116.txt (original) +++ peps/trunk/pep-3116.txt Tue Apr 10 20:37:53 2007 @@ -82,7 +82,7 @@ Returns number of bytes written, which may be ``< len(b)``. - ``.seek(pos: int, whence: int = 0) -> None`` + ``.seek(pos: int, whence: int = 0) -> int`` ``.tell() -> int`` @@ -283,7 +283,7 @@ The only supported use for the cookie is with .seek() with whence set to 0 (i.e. absolute seek). - ``.seek(pos: object, whence: int = 0) -> None`` + ``.seek(pos: object, whence: int = 0) -> int`` Seek to position ``pos``. If ``pos`` is non-zero, it must be a cookie returned from ``.tell()`` and ``whence`` must be zero. From python-checkins at python.org Tue Apr 10 20:55:04 2007 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 10 Apr 2007 20:55:04 +0200 (CEST) Subject: [Python-checkins] r54736 - peps/trunk/pep-3000.txt Message-ID: <20070410185504.6C7B81E4011@bag.python.org> Author: guido.van.rossum Date: Tue Apr 10 20:55:02 2007 New Revision: 54736 Modified: peps/trunk/pep-3000.txt Log: Note that stdlib changes are starting after 3.0a1 is released. Modified: peps/trunk/pep-3000.txt ============================================================================== --- peps/trunk/pep-3000.txt (original) +++ peps/trunk/pep-3000.txt Tue Apr 10 20:55:02 2007 @@ -56,6 +56,9 @@ submitted by the end of April 2007 (allowing time for discussion and implementation after the initial submission). +Note: standard library development is expected to ramp up after 3.0a1 +is released; it is exempt from the April 2007 PEP deadline. + I expect that there will be parallel Python 2.x and 3.x releases for some time; the Python 2.x releases will continue for a longer time than the traditional 2.x.y bugfix releases. Typically, we stop From python-checkins at python.org Tue Apr 10 22:58:54 2007 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 10 Apr 2007 22:58:54 +0200 (CEST) Subject: [Python-checkins] r54739 - peps/trunk/pep-3116.txt Message-ID: <20070410205854.5A4A01E400D@bag.python.org> Author: guido.van.rossum Date: Tue Apr 10 22:58:53 2007 New Revision: 54739 Modified: peps/trunk/pep-3116.txt Log: Like seek(), truncate() always returns the new current position. All write() methods return the number of bytes/characters written (for buffered and text files, this is always the lenth of the input). Modified: peps/trunk/pep-3116.txt ============================================================================== --- peps/trunk/pep-3116.txt (original) +++ peps/trunk/pep-3116.txt Tue Apr 10 22:58:53 2007 @@ -86,7 +86,7 @@ ``.tell() -> int`` - ``.truncate(n: int = None) -> None`` + ``.truncate(n: int = None) -> int`` ``.close() -> None`` @@ -162,17 +162,17 @@ ``.readinto(b: bytes) -> int`` - ``.write(b: bytes) -> None`` + ``.write(b: bytes) -> int`` Write ``b`` bytes to the buffer. The bytes are not guaranteed to be written to the Raw I/O object immediately; they may be - buffered. + buffered. Returns ``len(b)``. ``.seek(pos: int, whence: int = 0) -> int`` ``.tell() -> int`` - ``.truncate(pos: int = None) -> None`` + ``.truncate(pos: int = None) -> int`` ``.flush() -> None`` @@ -275,7 +275,7 @@ ``.read(n: int = -1) -> str`` - ``.write(s: str) -> None`` + ``.write(s: str) -> int`` ``.tell() -> object`` @@ -288,7 +288,7 @@ Seek to position ``pos``. If ``pos`` is non-zero, it must be a cookie returned from ``.tell()`` and ``whence`` must be zero. - ``.truncate(pos: object = None) -> None`` + ``.truncate(pos: object = None) -> int`` Like ``BufferedIOBase.truncate()``, except that ``pos`` (if not ``None``) must be a cookie previously returned by ``.tell()``. From python-checkins at python.org Tue Apr 10 23:39:42 2007 From: python-checkins at python.org (georg.brandl) Date: Tue, 10 Apr 2007 23:39:42 +0200 (CEST) Subject: [Python-checkins] r54741 - in python/trunk/Doc: lib/libamoeba.tex lib/libfm.tex lib/libposixfile.tex lib/libsun.tex lib/libunittest.tex mac/libframework.tex Message-ID: <20070410213942.22AB91E400D@bag.python.org> Author: georg.brandl Date: Tue Apr 10 23:39:38 2007 New Revision: 54741 Modified: python/trunk/Doc/lib/libamoeba.tex python/trunk/Doc/lib/libfm.tex python/trunk/Doc/lib/libposixfile.tex python/trunk/Doc/lib/libsun.tex python/trunk/Doc/lib/libunittest.tex python/trunk/Doc/mac/libframework.tex Log: Repair a duplicate label and some obsolete uses of \setindexsubitem. Modified: python/trunk/Doc/lib/libamoeba.tex ============================================================================== --- python/trunk/Doc/lib/libamoeba.tex (original) +++ python/trunk/Doc/lib/libamoeba.tex Tue Apr 10 23:39:38 2007 @@ -89,25 +89,24 @@ % The following methods are defined for capability objects. -\setindexsubitem{(capability method)} -\begin{funcdesc}{dir_list}{} +\begin{methoddesc}[capability]{dir_list}{} Returns a list of the names of the entries in an Amoeba directory. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{b_read}{offset, maxsize} +\begin{methoddesc}[capability]{b_read}{offset, maxsize} Reads (at most) \var{maxsize} bytes from a bullet file at offset \var{offset.} The data is returned as a string. EOF is reported as an empty string. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{b_size}{} +\begin{methoddesc}[capability]{b_size}{} Returns the size of a bullet file. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{dir_append}{} +\begin{methoddesc}[capability]{dir_append}{} \funcline{dir_delete}{} \funcline{dir_lookup}{} \funcline{dir_replace}{} @@ -116,17 +115,17 @@ functions, but with a path relative to the capability. (For paths beginning with a slash the capability is ignored, since this is the defined semantics for Amoeba.) -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{std_info}{} +\begin{methoddesc}[capability]{std_info}{} Returns the standard info string of the object. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{tod_gettime}{} +\begin{methoddesc}[capability]{tod_gettime}{} Returns the time (in seconds since the Epoch, in UCT, as for \POSIX) from a time server. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{tod_settime}{t} +\begin{methoddesc}[capability]{tod_settime}{t} Sets the time kept by a time server. -\end{funcdesc} +\end{methoddesc} Modified: python/trunk/Doc/lib/libfm.tex ============================================================================== --- python/trunk/Doc/lib/libfm.tex (original) +++ python/trunk/Doc/lib/libfm.tex Tue Apr 10 23:39:38 2007 @@ -55,40 +55,39 @@ Font handle objects support the following operations: -\setindexsubitem{(font handle method)} -\begin{funcdesc}{scalefont}{factor} +\begin{methoddesc}[font handle]{scalefont}{factor} Returns a handle for a scaled version of this font. Calls \code{fmscalefont(\var{fh}, \var{factor})}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{setfont}{} +\begin{methoddesc}[font handle]{setfont}{} Makes this font the current font. Note: the effect is undone silently when the font handle object is deleted. Calls \code{fmsetfont(\var{fh})}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{getfontname}{} +\begin{methoddesc}[font handle]{getfontname}{} Returns this font's name. Calls \code{fmgetfontname(\var{fh})}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{getcomment}{} +\begin{methoddesc}[font handle]{getcomment}{} Returns the comment string associated with this font. Raises an exception if there is none. Calls \code{fmgetcomment(\var{fh})}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{getfontinfo}{} +\begin{methoddesc}[font handle]{getfontinfo}{} Returns a tuple giving some pertinent data about this font. This is an interface to \code{fmgetfontinfo()}. The returned tuple contains the following numbers: \code{(}\var{printermatched}, \var{fixed_width}, \var{xorig}, \var{yorig}, \var{xsize}, \var{ysize}, \var{height}, \var{nglyphs}\code{)}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{getstrwidth}{string} +\begin{methoddesc}[font handle]{getstrwidth}{string} Returns the width, in pixels, of \var{string} when drawn in this font. Calls \code{fmgetstrwidth(\var{fh}, \var{string})}. -\end{funcdesc} +\end{methoddesc} Modified: python/trunk/Doc/lib/libposixfile.tex ============================================================================== --- python/trunk/Doc/lib/libposixfile.tex (original) +++ python/trunk/Doc/lib/libposixfile.tex Tue Apr 10 23:39:38 2007 @@ -62,8 +62,7 @@ The posixfile object defines the following additional methods: -\setindexsubitem{(posixfile method)} -\begin{funcdesc}{lock}{fmt, \optional{len\optional{, start\optional{, whence}}}} +\begin{methoddesc}[posixfile]{lock}{fmt, \optional{len\optional{, start\optional{, whence}}}} Lock the specified section of the file that the file object is referring to. The format is explained below in a table. The \var{len} argument specifies the length of the @@ -74,9 +73,9 @@ \constant{SEEK_CUR} or \constant{SEEK_END}. The default is \constant{SEEK_SET}. For more information about the arguments refer to the \manpage{fcntl}{2} manual page on your system. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{flags}{\optional{flags}} +\begin{methoddesc}[posixfile]{flags}{\optional{flags}} Set the specified flags for the file that the file object is referring to. The new flags are ORed with the old flags, unless specified otherwise. The format is explained below in a table. Without @@ -84,25 +83,25 @@ a string indicating the current flags is returned (this is the same as the \samp{?} modifier). For more information about the flags refer to the \manpage{fcntl}{2} manual page on your system. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{dup}{} +\begin{methoddesc}[posixfile]{dup}{} Duplicate the file object and the underlying file pointer and file descriptor. The resulting object behaves as if it were newly opened. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{dup2}{fd} +\begin{methoddesc}[posixfile]{dup2}{fd} Duplicate the file object and the underlying file pointer and file descriptor. The new object will have the given file descriptor. Otherwise the resulting object behaves as if it were newly opened. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{file}{} +\begin{methoddesc}[posixfile]{file}{} Return the standard file object that the posixfile object is based on. This is sometimes necessary for functions that insist on a standard file object. -\end{funcdesc} +\end{methoddesc} All methods raise \exception{IOError} when the request fails. Modified: python/trunk/Doc/lib/libsun.tex ============================================================================== --- python/trunk/Doc/lib/libsun.tex (original) +++ python/trunk/Doc/lib/libsun.tex Tue Apr 10 23:39:38 2007 @@ -3,3 +3,5 @@ The modules described in this chapter provide interfaces to features that are unique to SunOS 5 (also known as Solaris version 2). + +\localmoduletable Modified: python/trunk/Doc/lib/libunittest.tex ============================================================================== --- python/trunk/Doc/lib/libunittest.tex (original) +++ python/trunk/Doc/lib/libunittest.tex Tue Apr 10 23:39:38 2007 @@ -91,7 +91,7 @@ \end{seealso} -\subsection{Basic example \label{minimal-example}} +\subsection{Basic example \label{unittest-minimal-example}} The \module{unittest} module provides a rich set of tools for constructing and running tests. This section demonstrates that a Modified: python/trunk/Doc/mac/libframework.tex ============================================================================== --- python/trunk/Doc/mac/libframework.tex (original) +++ python/trunk/Doc/mac/libframework.tex Tue Apr 10 23:39:38 2007 @@ -189,8 +189,6 @@ Window objects have the following methods, among others: -\setindexsubitem{(Window method)} - \begin{methoddesc}[Window]{open}{} Override this method to open a window. Store the MacOS window-id in \member{self.wid} and call the \method{do_postopen()} method to From python-checkins at python.org Wed Apr 11 03:09:34 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 11 Apr 2007 03:09:34 +0200 (CEST) Subject: [Python-checkins] r54743 - peps/trunk/pep-3116.txt Message-ID: <20070411010934.8E6001E400F@bag.python.org> Author: guido.van.rossum Date: Wed Apr 11 03:09:33 2007 New Revision: 54743 Modified: peps/trunk/pep-3116.txt Log: Add newline arg to open(). Modified: peps/trunk/pep-3116.txt ============================================================================== --- peps/trunk/pep-3116.txt (original) +++ peps/trunk/pep-3116.txt Wed Apr 11 03:09:33 2007 @@ -413,11 +413,13 @@ The ``open()`` built-in function is specified by the following pseudo-code:: - def open(filename, mode="r", buffering=None, *, encoding=None): - assert isinstance(filename, str) + def open(filename, mode="r", buffering=None, *, + encoding=None, newline=None): + assert isinstance(filename, (str, int)) assert isinstance(mode, str) assert buffering is None or isinstance(buffering, int) assert encoding is None or isinstance(encoding, str) + assert newline in (None, "\n", "\r\n") modes = set(mode) if modes - set("arwb+t") or len(mode) > len(modes): raise ValueError("invalid mode: %r" % mode) @@ -434,7 +436,9 @@ if not (reading or writing or appending): raise ValueError("must have exactly one of read/write/append mode") if binary and encoding is not None: - raise ValueError("binary modes doesn't take an encoding") + raise ValueError("binary modes doesn't take an encoding arg") + if binary and newline is not None: + raise ValueError("binary modes doesn't take a newline arg") # XXX Need to spec the signature for FileIO() raw = FileIO(filename, mode) if buffering is None: @@ -456,9 +460,7 @@ if binary: return buffer assert text - # XXX Need to do something about universal newlines? - textio = TextIOWrapper(buffer) - return textio + return TextIOWrapper(buffer, encoding, newline) Copyright From python-checkins at python.org Wed Apr 11 15:39:02 2007 From: python-checkins at python.org (andrew.kuchling) Date: Wed, 11 Apr 2007 15:39:02 +0200 (CEST) Subject: [Python-checkins] r54746 - in python/trunk: Doc/lib/libcurses.tex Doc/whatsnew/whatsnew26.tex Lib/test/test_curses.py Misc/ACKS Modules/_cursesmodule.c Message-ID: <20070411133902.5A8F31E400F@bag.python.org> Author: andrew.kuchling Date: Wed Apr 11 15:39:00 2007 New Revision: 54746 Modified: python/trunk/Doc/lib/libcurses.tex python/trunk/Doc/whatsnew/whatsnew26.tex python/trunk/Lib/test/test_curses.py python/trunk/Misc/ACKS python/trunk/Modules/_cursesmodule.c Log: Add window.chgat() method, submitted via e-mail by Fabian Kreutz Modified: python/trunk/Doc/lib/libcurses.tex ============================================================================== --- python/trunk/Doc/lib/libcurses.tex (original) +++ python/trunk/Doc/lib/libcurses.tex Wed Apr 11 15:39:00 2007 @@ -646,6 +646,16 @@ corner characters are always used by this function. \end{methoddesc} +\begin{methoddesc}[window]{chgat}{\optional{y, x, } \optional{num,} attr} +Sets the attributes of \var{num} characters at the current cursor +position, or at position \code{(\var{y}, \var{x})} if supplied. If no +value of \var{num} is given or \var{num} = -1, the attribute will +be set on all the characters to the end of the line. +This function does not move the cursor. The changed line +will be touched using the \method{touchline} method so that the +contents will be redisplayed by the next window refresh. +\end{methoddesc} + \begin{methoddesc}[window]{clear}{} Like \method{erase()}, but also causes the whole window to be repainted upon next call to \method{refresh()}. Modified: python/trunk/Doc/whatsnew/whatsnew26.tex ============================================================================== --- python/trunk/Doc/whatsnew/whatsnew26.tex (original) +++ python/trunk/Doc/whatsnew/whatsnew26.tex Wed Apr 11 15:39:00 2007 @@ -135,6 +135,18 @@ (Contributed by Raymond Hettinger.) +\item New method in the \module{curses} module: +for a window, \method{chgat()} changes the display characters for a +certain number of characters on a single line. + +\begin{verbatim} +# Boldface text starting at y=0,x=21 +# and affecting the rest of the line. +stdscr.chgat(0,21, curses.A_BOLD) +\end{verbatim} + +(Contributed by Fabian Kreutz.) + \item New function in the \module{heapq} module: \function{merge(iter1, iter2, ...)} takes any number of iterables that return data Modified: python/trunk/Lib/test/test_curses.py ============================================================================== --- python/trunk/Lib/test/test_curses.py (original) +++ python/trunk/Lib/test/test_curses.py Wed Apr 11 15:39:00 2007 @@ -129,6 +129,12 @@ stdscr.touchline(5,5,0) stdscr.vline('a', 3) stdscr.vline('a', 3, curses.A_STANDOUT) + stdscr.chgat(5, 2, 3, curses.A_BLINK) + stdscr.chgat(3, curses.A_BOLD) + stdscr.chgat(5, 8, curses.A_UNDERLINE) + stdscr.chgat(curses.A_BLINK) + stdscr.refresh() + stdscr.vline(1,1, 'a', 3) stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT) Modified: python/trunk/Misc/ACKS ============================================================================== --- python/trunk/Misc/ACKS (original) +++ python/trunk/Misc/ACKS Wed Apr 11 15:39:00 2007 @@ -367,6 +367,7 @@ Joseph Koshy Bob Kras Holger Krekel +Fabian Kreutz Hannu Krosing Andrew Kuchling Vladimir Kushnir Modified: python/trunk/Modules/_cursesmodule.c ============================================================================== --- python/trunk/Modules/_cursesmodule.c (original) +++ python/trunk/Modules/_cursesmodule.c Wed Apr 11 15:39:00 2007 @@ -39,15 +39,15 @@ a given function, add it and send a patch. Here's a list of currently unsupported functions: - addchnstr addchstr chgat color_set define_key + addchnstr addchstr color_set define_key del_curterm delscreen dupwin inchnstr inchstr innstr keyok - mcprint mvaddchnstr mvaddchstr mvchgat mvcur mvinchnstr - mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr mvwchgat + mcprint mvaddchnstr mvaddchstr mvcur mvinchnstr + mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr mvwinchnstr mvwinchstr mvwinnstr newterm restartterm ripoffline scr_dump scr_init scr_restore scr_set scrl set_curterm set_term setterm tgetent tgetflag tgetnum tgetstr tgoto timeout tputs - vidattr vidputs waddchnstr waddchstr wchgat + vidattr vidputs waddchnstr waddchstr wcolor_set winchnstr winchstr winnstr wmouse_trafo wscrl Low-priority: @@ -620,6 +620,56 @@ } #endif +/* chgat, added by Fabian Kreutz */ + +static PyObject * +PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) +{ + int rtn; + int x, y; + int num = -1; + short color; + attr_t attr = A_NORMAL; + int use_xy = FALSE; + + switch (PyTuple_Size(args)) { + case 1: + if (!PyArg_ParseTuple(args,"l;attr", &attr)) + return NULL; + break; + case 2: + if (!PyArg_ParseTuple(args,"il;n,attr", &num, &attr)) + return NULL; + break; + case 3: + if (!PyArg_ParseTuple(args,"iil;int,int,attr", &y, &x, &attr)) + return NULL; + use_xy = TRUE; + break; + case 4: + if (!PyArg_ParseTuple(args,"iiil;int,int,n,attr", &y, &x, &num, &attr)) + return NULL; + use_xy = TRUE; + break; + default: + PyErr_SetString(PyExc_TypeError, "chgat requires 1 to 4 arguments"); + return NULL; + } + + color = (short)((attr >> 8) & 0xff); + attr = attr - (color << 8); + + if (use_xy == TRUE) { + rtn = mvwchgat(self->win,y,x,num,attr,color,NULL); + touchline(self->win,y,1); + } else { + getyx(self->win,y,x); + rtn = wchgat(self->win,num,attr,color,NULL); + touchline(self->win,y,1); + } + return PyCursesCheckERR(rtn, "chgat"); +} + static PyObject * PyCursesWindow_DelCh(PyCursesWindowObject *self, PyObject *args) @@ -1428,6 +1478,7 @@ {"attron", (PyCFunction)PyCursesWindow_wattron, METH_VARARGS}, {"attrset", (PyCFunction)PyCursesWindow_wattrset, METH_VARARGS}, {"bkgd", (PyCFunction)PyCursesWindow_Bkgd, METH_VARARGS}, + {"chgat", (PyCFunction)PyCursesWindow_ChgAt, METH_VARARGS}, {"bkgdset", (PyCFunction)PyCursesWindow_BkgdSet, METH_VARARGS}, {"border", (PyCFunction)PyCursesWindow_Border, METH_VARARGS}, {"box", (PyCFunction)PyCursesWindow_Box, METH_VARARGS}, From python-checkins at python.org Wed Apr 11 15:42:26 2007 From: python-checkins at python.org (andrew.kuchling) Date: Wed, 11 Apr 2007 15:42:26 +0200 (CEST) Subject: [Python-checkins] r54747 - python/trunk/Modules/_cursesmodule.c Message-ID: <20070411134226.02E311E4002@bag.python.org> Author: andrew.kuchling Date: Wed Apr 11 15:42:25 2007 New Revision: 54747 Modified: python/trunk/Modules/_cursesmodule.c Log: Point readers at the patch submission instructions Modified: python/trunk/Modules/_cursesmodule.c ============================================================================== --- python/trunk/Modules/_cursesmodule.c (original) +++ python/trunk/Modules/_cursesmodule.c Wed Apr 11 15:42:25 2007 @@ -35,9 +35,12 @@ /* -A number of SysV or ncurses functions don't have wrappers yet; if you need -a given function, add it and send a patch. Here's a list of currently -unsupported functions: +A number of SysV or ncurses functions don't have wrappers yet; if you +need a given function, add it and send a patch. See +http://www.python.org/dev/patches/ for instructions on how to submit +patches to Python. + +Here's a list of currently unsupported functions: addchnstr addchstr color_set define_key del_curterm delscreen dupwin inchnstr inchstr innstr keyok From python-checkins at python.org Wed Apr 11 15:47:13 2007 From: python-checkins at python.org (andrew.kuchling) Date: Wed, 11 Apr 2007 15:47:13 +0200 (CEST) Subject: [Python-checkins] r54748 - python/trunk/Doc/lib/libcurses.tex Message-ID: <20070411134713.9836C1E4002@bag.python.org> Author: andrew.kuchling Date: Wed Apr 11 15:47:13 2007 New Revision: 54748 Modified: python/trunk/Doc/lib/libcurses.tex Log: Describe undocumented third argument to touchline() Modified: python/trunk/Doc/lib/libcurses.tex ============================================================================== --- python/trunk/Doc/lib/libcurses.tex (original) +++ python/trunk/Doc/lib/libcurses.tex Wed Apr 11 15:47:13 2007 @@ -1024,9 +1024,11 @@ input at the end of that time. \end{methoddesc} -\begin{methoddesc}[window]{touchline}{start, count} +\begin{methoddesc}[window]{touchline}{start, count\optional{, changed}} Pretend \var{count} lines have been changed, starting with line -\var{start}. +\var{start}. If \var{changed} is supplied, it specifies +whether the affected lines are marked as +having been changed (\var{changed}=1) or unchanged (\var{changed}=0). \end{methoddesc} \begin{methoddesc}[window]{touchwin}{} From buildbot at python.org Wed Apr 11 15:47:32 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:47:32 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo trunk Message-ID: <20070411134732.5D6721E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520gentoo%2520trunk/builds/2130 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Wed Apr 11 15:47:33 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:47:33 +0000 Subject: [Python-checkins] buildbot failure in S-390 Debian trunk Message-ID: <20070411134733.02A921E4012@bag.python.org> The Buildbot has detected a new failure of S-390 Debian trunk. Full details are available at: http://www.python.org/dev/buildbot/all/S-390%2520Debian%2520trunk/builds/861 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Wed Apr 11 15:47:35 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:47:35 +0000 Subject: [Python-checkins] buildbot failure in MIPS Debian trunk Message-ID: <20070411134735.524071E4002@bag.python.org> The Buildbot has detected a new failure of MIPS Debian trunk. Full details are available at: http://www.python.org/dev/buildbot/all/MIPS%2520Debian%2520trunk/builds/747 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Wed Apr 11 15:47:35 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:47:35 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo trunk Message-ID: <20070411134735.C113E1E4011@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%2520gentoo%2520trunk/builds/1947 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Wed Apr 11 15:47:39 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:47:39 +0000 Subject: [Python-checkins] buildbot failure in x86 mvlgcc trunk Message-ID: <20070411134739.322A81E4011@bag.python.org> The Buildbot has detected a new failure of x86 mvlgcc trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520mvlgcc%2520trunk/builds/454 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Wed Apr 11 15:47:57 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:47:57 +0000 Subject: [Python-checkins] buildbot failure in x86 W2k trunk Message-ID: <20070411134757.353F31E4002@bag.python.org> The Buildbot has detected a new failure of x86 W2k trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520W2k%2520trunk/builds/201 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From python-checkins at python.org Wed Apr 11 15:47:59 2007 From: python-checkins at python.org (andrew.kuchling) Date: Wed, 11 Apr 2007 15:47:59 +0200 (CEST) Subject: [Python-checkins] r54749 - python/branches/release25-maint/Doc/lib/libcurses.tex Message-ID: <20070411134759.4F6EC1E4011@bag.python.org> Author: andrew.kuchling Date: Wed Apr 11 15:47:58 2007 New Revision: 54749 Modified: python/branches/release25-maint/Doc/lib/libcurses.tex Log: Describe undocumented third argument to touchline() Modified: python/branches/release25-maint/Doc/lib/libcurses.tex ============================================================================== --- python/branches/release25-maint/Doc/lib/libcurses.tex (original) +++ python/branches/release25-maint/Doc/lib/libcurses.tex Wed Apr 11 15:47:58 2007 @@ -1014,9 +1014,11 @@ input at the end of that time. \end{methoddesc} -\begin{methoddesc}[window]{touchline}{start, count} +\begin{methoddesc}[window]{touchline}{start, count\optional{, changed}} Pretend \var{count} lines have been changed, starting with line -\var{start}. +\var{start}. If \var{changed} is supplied, it specifies +whether the affected lines are marked as +having been changed (\var{changed}=1) or unchanged (\var{changed}=0). \end{methoddesc} \begin{methoddesc}[window]{touchwin}{} From buildbot at python.org Wed Apr 11 15:48:05 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:48:05 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc trunk Message-ID: <20070411134805.853511E4010@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc trunk. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%2520solaris10%2520gcc%2520trunk/builds/1934 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Wed Apr 11 15:48:07 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:48:07 +0000 Subject: [Python-checkins] buildbot failure in g4 osx.4 trunk Message-ID: <20070411134807.EC3471E4012@bag.python.org> The Buildbot has detected a new failure of g4 osx.4 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/g4%2520osx.4%2520trunk/builds/1942 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Wed Apr 11 15:49:05 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:49:05 +0000 Subject: [Python-checkins] buildbot failure in alpha Tru64 5.1 trunk Message-ID: <20070411134905.63FEF1E4002@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%2520trunk/builds/1615 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Wed Apr 11 15:53:47 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 13:53:47 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk trunk Message-ID: <20070411135347.EA66B1E400D@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%2520Ubuntu%2520trunk%2520trunk/builds/574 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,georg.brandl BUILD FAILED: failed svn sincerely, -The Buildbot From kristjan at ccpgames.com Wed Apr 11 15:15:29 2007 From: kristjan at ccpgames.com (=?iso-8859-1?Q?Kristj=E1n_Valur_J=F3nsson?=) Date: Wed, 11 Apr 2007 13:15:29 +0000 Subject: [Python-checkins] svn dead? Message-ID: <4E9372E6B2234D4F859320D896059A9508BF48EBAF@exchis.ccp.ad.local> The SVN repository hasn't answered http requests since this morning. Anyone know what is up with that? Kristj?n -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/python-checkins/attachments/20070411/7674304d/attachment.html From barry at python.org Wed Apr 11 16:34:28 2007 From: barry at python.org (Barry Warsaw) Date: Wed, 11 Apr 2007 10:34:28 -0400 Subject: [Python-checkins] svn dead? In-Reply-To: <4E9372E6B2234D4F859320D896059A9508BF48EBAF@exchis.ccp.ad.local> References: <4E9372E6B2234D4F859320D896059A9508BF48EBAF@exchis.ccp.ad.local> Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Apr 11, 2007, at 9:15 AM, Kristj?n Valur J?nsson wrote: > The SVN repository hasn?t answered http requests since this > morning. Anyone know what is up with that? Known breakage. We're working on it. - -Barry -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Darwin) iQCVAwUBRhzx9HEjvBPtnXfVAQJwEQQApPQumTtLJPhlRU9a44dOuRI9DFGMQePD 6Hbsux0HcKvcLpR5QQlsUrKEAyGOt2qDm1YpoWM3uwSN68JnnlAc0iiYUQe1s8/U pRBy18eIhd9mGR2F2k9ZdDX0tqDapyVlc5bDb2jAaWSMwMO0AAUXyz4gtIP7thDW b9vZ18YXnvQ= =9riM -----END PGP SIGNATURE----- From barry at python.org Wed Apr 11 17:10:52 2007 From: barry at python.org (Barry Warsaw) Date: Wed, 11 Apr 2007 11:10:52 -0400 Subject: [Python-checkins] svn dead? In-Reply-To: References: <4E9372E6B2234D4F859320D896059A9508BF48EBAF@exchis.ccp.ad.local> Message-ID: <022AFF34-4BAE-4B26-BA3E-9823D9253B94@python.org> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Apr 11, 2007, at 10:34 AM, Barry Warsaw wrote: > On Apr 11, 2007, at 9:15 AM, Kristj?n Valur J?nsson wrote: >> The SVN repository hasn?t answered http requests since this >> morning. Anyone know what is up with that? > Known breakage. We're working on it. svn.python.org is back online now (both http and https). I'll take this opportunity to mention that we've ordered a new ssl cert for our expired one on https. It hasn't arrived yet, but should within a few days. I'll make another announcement when the new cert is installed. Cheers, - -Barry -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Darwin) iQCVAwUBRhz6fXEjvBPtnXfVAQJKYAQAhtF4kA/5HeEvSZhktR3zAHkCZMjDcs1M sPeaAOOF55Pej0HagUi6haYcxoGeFOiGYq0pVzhu2FnuuUIi5LIOumn65w1s7xci z14OhYquTOMTyY2leyZdIj8eywg9ZMtKPXHS5spCm912/9gyuqYI6X9pkPakSRZ/ 0kD1/DmVvhE= =h93N -----END PGP SIGNATURE----- From python-checkins at python.org Wed Apr 11 17:27:07 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 11 Apr 2007 17:27:07 +0200 (CEST) Subject: [Python-checkins] r54751 - sandbox/trunk/2to3/fixes/util.py Message-ID: <20070411152707.CD3A31E4002@bag.python.org> Author: collin.winter Date: Wed Apr 11 17:27:03 2007 New Revision: 54751 Modified: sandbox/trunk/2to3/fixes/util.py Log: Add a KeywordArg() macro. Modified: sandbox/trunk/2to3/fixes/util.py ============================================================================== --- sandbox/trunk/2to3/fixes/util.py (original) +++ sandbox/trunk/2to3/fixes/util.py Wed Apr 11 17:27:03 2007 @@ -15,6 +15,10 @@ ### Common node-construction "macros" ########################################################### +def KeywordArg(keyword, value): + return Node(syms.argument, + [keyword, Leaf(token.EQUAL, '='), value]) + def LParen(): return Leaf(token.LPAR, "(") From python-checkins at python.org Wed Apr 11 17:57:49 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 11 Apr 2007 17:57:49 +0200 (CEST) Subject: [Python-checkins] r54752 - in sandbox/trunk/2to3: pytree.py tests/test_pytree.py Message-ID: <20070411155749.123E41E4016@bag.python.org> Author: collin.winter Date: Wed Apr 11 17:57:45 2007 New Revision: 54752 Modified: sandbox/trunk/2to3/pytree.py sandbox/trunk/2to3/tests/test_pytree.py Log: Add append_child(), insert_child() and set_child() methods to pytree.Node to simplify child-manipulating code. Modified: sandbox/trunk/2to3/pytree.py ============================================================================== --- sandbox/trunk/2to3/pytree.py (original) +++ sandbox/trunk/2to3/pytree.py Wed Apr 11 17:57:45 2007 @@ -209,6 +209,25 @@ if not self.children: return "" return self.children[0].get_prefix() + + def set_child(self, i, child): + """Equivalent to 'node.children[i] = child'. This method also sets the + child's parent attribute appropriately.""" + child.parent = self + self.children[i].parent = None + self.children[i] = child + + def insert_child(self, i, child): + """Equivalent to 'node.children.insert(i, child)'. This method also + sets the child's parent attribute appropriately.""" + child.parent = self + self.children.insert(i, child) + + def append_child(self, child): + """Equivalent to 'node.children.append(child)'. This method also + sets the child's parent attribute appropriately.""" + child.parent = self + self.children.append(child) class Leaf(Base): Modified: sandbox/trunk/2to3/tests/test_pytree.py ============================================================================== --- sandbox/trunk/2to3/tests/test_pytree.py (original) +++ sandbox/trunk/2to3/tests/test_pytree.py Wed Apr 11 17:57:45 2007 @@ -209,6 +209,59 @@ l1 = pytree.Leaf(100, "foo") l1.remove() self.assertEqual(l1.parent, None) + + def testNodeSetChild(self): + l1 = pytree.Leaf(100, "foo") + n1 = pytree.Node(1000, [l1]) + + l2 = pytree.Leaf(100, "bar") + n1.set_child(0, l2) + self.assertEqual(l1.parent, None) + self.assertEqual(l2.parent, n1) + self.assertEqual(n1.children, [l2]) + + n2 = pytree.Node(1000, [l1]) + n2.set_child(0, n1) + self.assertEqual(l1.parent, None) + self.assertEqual(n1.parent, n2) + self.assertEqual(n2.parent, None) + self.assertEqual(n2.children, [n1]) + + self.assertRaises(IndexError, n1.set_child, 4, l2) + # I don't care what it raises, so long as it's an exception + self.assertRaises(Exception, n1.set_child, 0, list) + + def testNodeInsertChild(self): + l1 = pytree.Leaf(100, "foo") + n1 = pytree.Node(1000, [l1]) + + l2 = pytree.Leaf(100, "bar") + n1.insert_child(0, l2) + self.assertEqual(l2.parent, n1) + self.assertEqual(n1.children, [l2, l1]) + + l3 = pytree.Leaf(100, "abc") + n1.insert_child(2, l3) + self.assertEqual(n1.children, [l2, l1, l3]) + + # I don't care what it raises, so long as it's an exception + self.assertRaises(Exception, n1.insert_child, 0, list) + + def testNodeAppendChild(self): + n1 = pytree.Node(1000, []) + + l1 = pytree.Leaf(100, "foo") + n1.append_child(l1) + self.assertEqual(l1.parent, n1) + self.assertEqual(n1.children, [l1]) + + l2 = pytree.Leaf(100, "bar") + n1.append_child(l2) + self.assertEqual(l2.parent, n1) + self.assertEqual(n1.children, [l1, l2]) + + # I don't care what it raises, so long as it's an exception + self.assertRaises(Exception, n1.append_child, list) class TestPatterns(support.TestCase): From python-checkins at python.org Wed Apr 11 17:59:19 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 11 Apr 2007 17:59:19 +0200 (CEST) Subject: [Python-checkins] r54753 - sandbox/trunk/2to3/tests/test_pytree.py Message-ID: <20070411155919.C28851E4002@bag.python.org> Author: collin.winter Date: Wed Apr 11 17:59:15 2007 New Revision: 54753 Modified: sandbox/trunk/2to3/tests/test_pytree.py Log: Strengthen two assertions. Modified: sandbox/trunk/2to3/tests/test_pytree.py ============================================================================== --- sandbox/trunk/2to3/tests/test_pytree.py (original) +++ sandbox/trunk/2to3/tests/test_pytree.py Wed Apr 11 17:59:15 2007 @@ -185,7 +185,7 @@ n2 = pytree.Node(1000, [n1]) self.assertEqual(n1.remove(), 0) - self.failIf(n1 in n2.children) + self.assertEqual(n2.children, []) self.assertEqual(l1.parent, n1) self.assertEqual(n1.parent, None) self.assertEqual(n2.parent, None) @@ -194,7 +194,7 @@ self.assertEqual(l2.remove(), 1) self.assertEqual(l1.remove(), 0) - self.failIf(l1 in n1.children) + self.assertEqual(n1.children, []) self.assertEqual(l1.parent, None) self.assertEqual(n1.parent, None) self.assertEqual(n2.parent, None) From python-checkins at python.org Wed Apr 11 19:16:25 2007 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2007 19:16:25 +0200 (CEST) Subject: [Python-checkins] r54757 - python/trunk/Objects/exceptions.c python/trunk/Objects/longobject.c Message-ID: <20070411171625.EC97F1E4004@bag.python.org> Author: georg.brandl Date: Wed Apr 11 19:16:24 2007 New Revision: 54757 Modified: python/trunk/Objects/exceptions.c python/trunk/Objects/longobject.c Log: Add some missing NULL checks which trigger crashes on low-memory conditions. Found by Victor Stinner. Will backport when 2.5 branch is unfrozen. Modified: python/trunk/Objects/exceptions.c ============================================================================== --- python/trunk/Objects/exceptions.c (original) +++ python/trunk/Objects/exceptions.c Wed Apr 11 19:16:24 2007 @@ -33,6 +33,8 @@ PyBaseExceptionObject *self; self = (PyBaseExceptionObject *)type->tp_alloc(type, 0); + if (!self) + return NULL; /* the dict is created on the fly in PyObject_GenericSetAttr */ self->message = self->dict = NULL; Modified: python/trunk/Objects/longobject.c ============================================================================== --- python/trunk/Objects/longobject.c (original) +++ python/trunk/Objects/longobject.c Wed Apr 11 19:16:24 2007 @@ -1739,6 +1739,8 @@ a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) { /* |a| < |b|. */ *pdiv = _PyLong_New(0); + if (*pdiv == NULL) + return -1; Py_INCREF(a); *prem = (PyLongObject *) a; return 0; @@ -1749,6 +1751,10 @@ if (z == NULL) return -1; *prem = (PyLongObject *) PyLong_FromLong((long)rem); + if (*prem == NULL) { + Py_DECREF(z); + return -1; + } } else { z = x_divrem(a, b, prem); @@ -3204,6 +3210,8 @@ { if (PyInt_Check(*pw)) { *pw = PyLong_FromLong(PyInt_AS_LONG(*pw)); + if (*pw == NULL) + return -1; Py_INCREF(*pv); return 0; } From buildbot at python.org Wed Apr 11 19:54:10 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 17:54:10 +0000 Subject: [Python-checkins] buildbot warnings in amd64 gentoo trunk Message-ID: <20070411175411.03F241E4010@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%2520gentoo%2520trunk/builds/1948 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_timeout make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Apr 11 19:57:32 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 17:57:32 +0000 Subject: [Python-checkins] buildbot warnings in alpha Tru64 5.1 trunk Message-ID: <20070411175732.A929F1E4002@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%2520trunk/builds/1616 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From barry at python.org Wed Apr 11 20:05:17 2007 From: barry at python.org (Barry Warsaw) Date: Wed, 11 Apr 2007 14:05:17 -0400 Subject: [Python-checkins] svn.python.org In-Reply-To: <022AFF34-4BAE-4B26-BA3E-9823D9253B94@python.org> References: <4E9372E6B2234D4F859320D896059A9508BF48EBAF@exchis.ccp.ad.local> <022AFF34-4BAE-4B26-BA3E-9823D9253B94@python.org> Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Apr 11, 2007, at 11:10 AM, Barry Warsaw wrote: > I'll take this opportunity to mention that we've ordered a new ssl > cert for our expired one on https. It hasn't arrived yet, but > should within a few days. I'll make another announcement when the > new cert is installed. The new certificate has been installed. It's good until 2010. Please let me know if you have any problems with it. Cheers, - -Barry -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Darwin) iQCVAwUBRh0jXnEjvBPtnXfVAQKuQwP/QZr/mP6bppUDw4Lz1CoKeWlICTSk0Qg/ g+RdFJFXgpwEwWUPRc8w6Cg7yxQZkpaWzoI1+wQRf10G6sw0JUWzN6A2wgBc0lNy 7W2sFFghjQ55gFqoYIGDs3dhLlKcNHhyhTWPFKTw5cnQ41GV9fVLXVtuMqGzeylg dFGUcXqazdU= =jv2x -----END PGP SIGNATURE----- From buildbot at python.org Wed Apr 11 20:13:55 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Apr 2007 18:13:55 +0000 Subject: [Python-checkins] buildbot warnings in sparc solaris10 gcc trunk Message-ID: <20070411181355.EA5131E401E@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc trunk. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%2520solaris10%2520gcc%2520trunk/builds/1935 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl Build had warnings: warnings test Excerpt from the test logfile: Traceback (most recent call last): File "/opt/users/buildbot/slave/trunk.loewis-sun/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/opt/users/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_socketserver.py", line 93, in run svr.serve_a_few() File "/opt/users/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_socketserver.py", line 35, in serve_a_few self.handle_request() File "/opt/users/buildbot/slave/trunk.loewis-sun/build/Lib/SocketServer.py", line 224, in handle_request self.handle_error(request, client_address) File "/opt/users/buildbot/slave/trunk.loewis-sun/build/Lib/SocketServer.py", line 222, in handle_request self.process_request(request, client_address) File "/opt/users/buildbot/slave/trunk.loewis-sun/build/Lib/SocketServer.py", line 429, in process_request self.collect_children() File "/opt/users/buildbot/slave/trunk.loewis-sun/build/Lib/SocketServer.py", line 425, in collect_children self.active_children.remove(pid) ValueError: list.remove(x): x not in list 2 tests failed: test_pty test_socketserver ====================================================================== FAIL: test_basic (test.test_pty.PtyTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/opt/users/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_pty.py", line 76, in test_basic normalize_output(s1)) AssertionError: 'I wish to buy a fish license.\n' != '' sincerely, -The Buildbot From python-checkins at python.org Wed Apr 11 20:41:02 2007 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 11 Apr 2007 20:41:02 +0200 (CEST) Subject: [Python-checkins] r54760 - in python/trunk: Lib/test/test_slice.py Misc/NEWS Objects/sliceobject.c Message-ID: <20070411184102.BA6CB1E4002@bag.python.org> Author: raymond.hettinger Date: Wed Apr 11 20:40:58 2007 New Revision: 54760 Modified: python/trunk/Lib/test/test_slice.py python/trunk/Misc/NEWS python/trunk/Objects/sliceobject.c Log: SF 1191699: Make slices picklable Modified: python/trunk/Lib/test/test_slice.py ============================================================================== --- python/trunk/Lib/test/test_slice.py (original) +++ python/trunk/Lib/test/test_slice.py Wed Apr 11 20:40:58 2007 @@ -2,6 +2,7 @@ import unittest from test import test_support +from cPickle import loads, dumps import sys @@ -102,6 +103,13 @@ x[1:2] = 42 self.assertEquals(tmp, [(1, 2, 42)]) + def test_pickle(self): + s = slice(10, 20, 3) + for protocol in (0,1,2): + t = loads(dumps(s, protocol)) + self.assertEqual(s, t) + self.assertEqual(s.indices(15), t.indices(15)) + self.assertNotEqual(id(s), id(t)) def test_main(): test_support.run_unittest(SliceTest) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Apr 11 20:40:58 2007 @@ -12,6 +12,8 @@ Core and builtins ----------------- +- Request #1191699: Slices can now be pickled. + - Patch #1682205: a TypeError while unpacking an iterable is no longer masked by a generic one with the message "unpack non-sequence". Modified: python/trunk/Objects/sliceobject.c ============================================================================== --- python/trunk/Objects/sliceobject.c (original) +++ python/trunk/Objects/sliceobject.c Wed Apr 11 20:40:58 2007 @@ -274,9 +274,19 @@ S. Out of bounds indices are clipped in a manner consistent with the\n\ handling of normal slices."); +static PyObject * +slice_reduce(PySliceObject* self) +{ + return Py_BuildValue("O(OOO)", self->ob_type, self->start, self->stop, self->step); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + static PyMethodDef slice_methods[] = { {"indices", (PyCFunction)slice_indices, METH_O, slice_indices_doc}, + {"__reduce__", (PyCFunction)slice_reduce, + METH_NOARGS, reduce_doc}, {NULL, NULL} }; From python-checkins at python.org Wed Apr 11 21:25:14 2007 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2007 21:25:14 +0200 (CEST) Subject: [Python-checkins] r54762 - python/trunk/Lib/cgitb.py Message-ID: <20070411192514.3C9721E4003@bag.python.org> Author: georg.brandl Date: Wed Apr 11 21:25:11 2007 New Revision: 54762 Modified: python/trunk/Lib/cgitb.py Log: Exceptions are no longer old-style instances. Fix accordingly. Modified: python/trunk/Lib/cgitb.py ============================================================================== --- python/trunk/Lib/cgitb.py (original) +++ python/trunk/Lib/cgitb.py Wed Apr 11 21:25:11 2007 @@ -167,7 +167,7 @@ exception = ['

%s: %s' % (strong(pydoc.html.escape(str(etype))), pydoc.html.escape(str(evalue)))] - if type(evalue) is types.InstanceType: + if isinstance(evalue, BaseException): for name in dir(evalue): if name[:1] == '_': continue value = pydoc.html.repr(getattr(evalue, name)) @@ -239,7 +239,7 @@ frames.append('\n%s\n' % '\n'.join(rows)) exception = ['%s: %s' % (str(etype), str(evalue))] - if type(evalue) is types.InstanceType: + if isinstance(evalue, BaseException): for name in dir(evalue): value = pydoc.text.repr(getattr(evalue, name)) exception.append('\n%s%s = %s' % (" "*4, name, value)) From python-checkins at python.org Thu Apr 12 01:28:45 2007 From: python-checkins at python.org (georg.brandl) Date: Thu, 12 Apr 2007 01:28:45 +0200 (CEST) Subject: [Python-checkins] r54763 - in python/trunk/Doc: api/init.tex inst/inst.tex lib/libposixpath.tex mac/using.tex Message-ID: <20070411232845.D721A1E4002@bag.python.org> Author: georg.brandl Date: Thu Apr 12 01:28:44 2007 New Revision: 54763 Modified: python/trunk/Doc/api/init.tex python/trunk/Doc/inst/inst.tex python/trunk/Doc/lib/libposixpath.tex python/trunk/Doc/mac/using.tex Log: Repair missing spaces after \UNIX. Modified: python/trunk/Doc/api/init.tex ============================================================================== --- python/trunk/Doc/api/init.tex (original) +++ python/trunk/Doc/api/init.tex Thu Apr 12 01:28:44 2007 @@ -245,7 +245,7 @@ program name (set by \cfunction{Py_SetProgramName()} above) and some environment variables. The returned string consists of a series of directory names separated by a platform dependent delimiter - character. The delimiter character is \character{:} on \UNIX and Mac OS X, + character. The delimiter character is \character{:} on \UNIX{} and Mac OS X, \character{;} on Windows. The returned string points into static storage; the caller should not modify its value. The value is available to Python code as the list Modified: python/trunk/Doc/inst/inst.tex ============================================================================== --- python/trunk/Doc/inst/inst.tex (original) +++ python/trunk/Doc/inst/inst.tex Thu Apr 12 01:28:44 2007 @@ -296,7 +296,7 @@ \filevar{prefix} and \filevar{exec-prefix} stand for the directories that Python is installed to, and where it finds its libraries at run-time. They are always the same under Windows, and very -often the same under \UNIX and Mac OS X. You can find out what your Python +often the same under \UNIX{} and Mac OS X. You can find out what your Python installation uses for \filevar{prefix} and \filevar{exec-prefix} by running Python in interactive mode and typing a few simple commands. Under \UNIX, just type \code{python} at the shell prompt. Under Modified: python/trunk/Doc/lib/libposixpath.tex ============================================================================== --- python/trunk/Doc/lib/libposixpath.tex (original) +++ python/trunk/Doc/lib/libposixpath.tex Thu Apr 12 01:28:44 2007 @@ -58,7 +58,7 @@ \end{funcdesc} \begin{funcdesc}{expanduser}{path} -On \UNIX and Windows, return the argument with an initial component of +On \UNIX{} and Windows, return the argument with an initial component of \samp{\~} or \samp{\~\var{user}} replaced by that \var{user}'s home directory. On \UNIX, an initial \samp{\~} is replaced by the environment variable Modified: python/trunk/Doc/mac/using.tex ============================================================================== --- python/trunk/Doc/mac/using.tex (original) +++ python/trunk/Doc/mac/using.tex Thu Apr 12 01:28:44 2007 @@ -2,7 +2,7 @@ \sectionauthor{Bob Savage}{bobsavage at mac.com} Python on a Macintosh running Mac OS X is in principle very similar to -Python on any other \UNIX platform, but there are a number of additional +Python on any other \UNIX{} platform, but there are a number of additional features such as the IDE and the Package Manager that are worth pointing out. Python on Mac OS 9 or earlier can be quite different from Python on From python-checkins at python.org Thu Apr 12 04:06:33 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Apr 2007 04:06:33 +0200 (CEST) Subject: [Python-checkins] r54764 - sandbox/trunk/pep0/pep0.py Message-ID: <20070412020633.114131E4003@bag.python.org> Author: brett.cannon Date: Thu Apr 12 04:06:30 2007 New Revision: 54764 Modified: sandbox/trunk/pep0/pep0.py Log: Allow for specifying a single PEP file (for testing purposes). Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Thu Apr 12 04:06:30 2007 @@ -139,13 +139,15 @@ from sys import argv, stdout if not argv[1:]: - directory = '.' + path = '.' else: - directory = argv[1] - peps = consume_headers(directory) + path = argv[1] + if os.path.isdir(path): + peps = consume_headers(directory) + else: + peps = [consume_pep(path)] - output = stdout for pep in peps: - write_pep(pep, output) + write_pep(pep, stdout) #meta, info, accepted, open_, done, empty, dead = sort_peps(peps) From python-checkins at python.org Thu Apr 12 04:07:03 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Apr 2007 04:07:03 +0200 (CEST) Subject: [Python-checkins] r54765 - sandbox/trunk/pep0/test_pep0.py Message-ID: <20070412020703.AD9671E4003@bag.python.org> Author: brett.cannon Date: Thu Apr 12 04:07:02 2007 New Revision: 54765 Modified: sandbox/trunk/pep0/test_pep0.py Log: Strengthen author parsing. Currently leads to a failure. Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Thu Apr 12 04:07:02 2007 @@ -36,22 +36,18 @@ # Name , # email (name), # Name. - author = "Guido van Rossum" - str_rep = "%s " % author - self.failUnlessEqual(pep0.handle_author(str_rep), [author]) - str_rep += ',' - self.failUnlessEqual(pep0.handle_author(str_rep), [author]) - str_rep = "email (%s)" % author - self.failUnlessEqual(pep0.handle_author(str_rep), [author]) - str_rep += ',' - self.failUnlessEqual(pep0.handle_author(str_rep), [author]) - str_rep = author - self.failUnlessEqual(pep0.handle_author(str_rep), [author]) - str_rep += ',' - self.failUnlessEqual(pep0.handle_author(str_rep), [author]) authors = ["Guido van Rossum", "Brett Cannon"] - str_rep = ', '.join(authors) - self.failUnlessEqual(pep0.handle_author(str_rep), authors) + formats = ["%s ", "email (%s)", "%s"] + for format in formats: + rep = format % authors[0] + expect = authors[0:1] + self.failUnlessEqual(pep0.handle_author(rep), expect) + rep += ',' + self.failUnlessEqual(pep0.handle_author(rep), expect) + rep += format % authors[1] + self.failUnlessEqual(pep0.handle_author(rep), authors) + rep += ',' + self.failUnlessEqual(pep0.handle_author(rep), authors) class ParseMetaDataTests(unittest.TestCase): From python-checkins at python.org Thu Apr 12 04:50:48 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 04:50:48 +0200 (CEST) Subject: [Python-checkins] r54766 - sandbox/trunk/2to3/HACKING sandbox/trunk/2to3/README Message-ID: <20070412025048.B80D41E400D@bag.python.org> Author: collin.winter Date: Thu Apr 12 04:50:44 2007 New Revision: 54766 Modified: sandbox/trunk/2to3/HACKING sandbox/trunk/2to3/README Log: Add a TODO section to HACKING (and a pointer to it from README). Modified: sandbox/trunk/2to3/HACKING ============================================================================== --- sandbox/trunk/2to3/HACKING (original) +++ sandbox/trunk/2to3/HACKING Thu Apr 12 04:50:44 2007 @@ -6,3 +6,26 @@ * If your fixer works by changing a node's children list or a leaf's value, be sure to call the node/leaf's changed() method. This to be sure refactor.py will recognize that the tree has changed. + + + +TODO + + Simple: + ####### + + * Refactor common code out of fixes/fix_*.py into fixes.util (ongoing). + + + Complex: + ######## + + * Replace tuple usage in patterns and node.children with lists (95% + done). Simplify fixers accordingly (mostly done, I think). + + * Come up with a scheme to hide the details of suite indentation (some + kind of custom pytree node for suites, probably). This will + automatically reindent all code with spaces, tied into a refactor.py + flag that allows you to specify the indent level. + + * Remove the need to explicitly assign a node's parent attribute. Modified: sandbox/trunk/2to3/README ============================================================================== --- sandbox/trunk/2to3/README (original) +++ sandbox/trunk/2to3/README Thu Apr 12 04:50:44 2007 @@ -150,6 +150,13 @@ it while at Google to suit the needs of this refactoring tool. +Development +=========== + +The HACKING file has a list of TODOs -- some simple, some complex -- that +would make good introductions for anyone new to 2to3. + + Licensing ========= From python-checkins at python.org Thu Apr 12 04:54:30 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 04:54:30 +0200 (CEST) Subject: [Python-checkins] r54767 - sandbox/trunk/2to3/README Message-ID: <20070412025430.835231E4015@bag.python.org> Author: collin.winter Date: Thu Apr 12 04:54:30 2007 New Revision: 54767 Modified: sandbox/trunk/2to3/README Log: Update licensing section. Modified: sandbox/trunk/2to3/README ============================================================================== --- sandbox/trunk/2to3/README (original) +++ sandbox/trunk/2to3/README Thu Apr 12 04:54:30 2007 @@ -162,8 +162,16 @@ The original pgen2 module is copyrighted by Elemental Security. All new code I wrote specifically for this tool is copyrighted by Google. -New code by others (notably Collin Winter) is copyrighted by the -respective authors. All code (whether by me or by others) is licensed -to the PSF under a contributor agreement. +New code by others is copyrighted by the respective authors. All code +(whether by me or by others) is licensed to the PSF under a contributor +agreement. --Guido van Rossum + + +All code I wrote specifically for this tool before 9 April 2007 is +copyrighted by me. All new code I wrote specifically for this tool after +9 April 2007 is copyrighted by Google. Regardless, my contributions are +licensed to the PSF under a contributor agreement. + +--Collin Winter From python-checkins at python.org Thu Apr 12 04:59:27 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 04:59:27 +0200 (CEST) Subject: [Python-checkins] r54768 - sandbox/trunk/2to3/fixes/fix_dict.py Message-ID: <20070412025927.9348E1E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 04:59:25 2007 New Revision: 54768 Modified: sandbox/trunk/2to3/fixes/fix_dict.py Log: Reindent to four spaces, not Google's two :) Modified: sandbox/trunk/2to3/fixes/fix_dict.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_dict.py (original) +++ sandbox/trunk/2to3/fixes/fix_dict.py Thu Apr 12 04:59:25 2007 @@ -29,65 +29,64 @@ from fixes.util import Name, Call, LParen, RParen class FixDict(basefix.BaseFix): - - PATTERN = """ - power< head=any+ + PATTERN = """ + power< head=any+ trailer< '.' method=('keys'|'items'|'values'| 'iterkeys'|'iteritems'|'itervalues') > trailer< '(' ')' > tail=any* - > - """ - - def transform(self, node): - results = self.match(node) - head = results["head"] - method = results["method"][0].value # Extract method name - tail = results["tail"] - syms = self.syms - isiter = method.startswith("iter") - if isiter: - method = method[4:] - assert method in ("keys", "items", "values"), repr(method) - head = [n.clone() for n in head] - tail = [n.clone() for n in tail] - special = not tail and self.in_special_context(node, isiter) - args = head + [pytree.Node(syms.trailer, - [pytree.Leaf(token.DOT, '.'), - Name(method)]), - pytree.Node(syms.trailer, [LParen(), RParen()])] - new = pytree.Node(syms.power, args) - if not special: - new.set_prefix("") - new = Call(Name(isiter and "iter" or "list"), [new]) - if tail: - new = pytree.Node(syms.power, [new] + tail) - new.set_prefix(node.get_prefix()) - return new - - P1 = "power< func=NAME trailer< '(' node=any ')' > any* >" - p1 = patcomp.PatternCompiler().compile_pattern(P1) - - P2 = """for_stmt< 'for' any 'in' node=any ':' any* > - | list_for< 'for' any 'in' node=any any* > - | gen_for< 'for' any 'in' node=any any* > - """ - p2 = patcomp.PatternCompiler().compile_pattern(P2) + > + """ - def in_special_context(self, node, isiter): - if node.parent is None: - return False - results = {} - if (node.parent.parent is not None and - self.p1.match(node.parent.parent, results) and - results["node"] is node): - if isiter: - # iter(d.iterkeys()) -> iter(d.keys()), etc. - return results["func"].value in ("iter", "list", "sorted") - else: - # list(d.keys()) -> list(d.keys()), etc. - return results["func"].value in ("list", "sorted") - if not isiter: - return False - # for ... in d.iterkeys() -> for ... in d.keys(), etc. - return self.p2.match(node.parent, results) and results["node"] is node + def transform(self, node): + results = self.match(node) + head = results["head"] + method = results["method"][0].value # Extract method name + tail = results["tail"] + syms = self.syms + isiter = method.startswith("iter") + if isiter: + method = method[4:] + assert method in ("keys", "items", "values"), repr(method) + head = [n.clone() for n in head] + tail = [n.clone() for n in tail] + special = not tail and self.in_special_context(node, isiter) + args = head + [pytree.Node(syms.trailer, + [pytree.Leaf(token.DOT, '.'), + Name(method)]), + pytree.Node(syms.trailer, [LParen(), RParen()])] + new = pytree.Node(syms.power, args) + if not special: + new.set_prefix("") + new = Call(Name(isiter and "iter" or "list"), [new]) + if tail: + new = pytree.Node(syms.power, [new] + tail) + new.set_prefix(node.get_prefix()) + return new + + P1 = "power< func=NAME trailer< '(' node=any ')' > any* >" + p1 = patcomp.PatternCompiler().compile_pattern(P1) + + P2 = """for_stmt< 'for' any 'in' node=any ':' any* > + | list_for< 'for' any 'in' node=any any* > + | gen_for< 'for' any 'in' node=any any* > + """ + p2 = patcomp.PatternCompiler().compile_pattern(P2) + + def in_special_context(self, node, isiter): + if node.parent is None: + return False + results = {} + if (node.parent.parent is not None and + self.p1.match(node.parent.parent, results) and + results["node"] is node): + if isiter: + # iter(d.iterkeys()) -> iter(d.keys()), etc. + return results["func"].value in ("iter", "list", "sorted") + else: + # list(d.keys()) -> list(d.keys()), etc. + return results["func"].value in ("list", "sorted") + if not isiter: + return False + # for ... in d.iterkeys() -> for ... in d.keys(), etc. + return self.p2.match(node.parent, results) and results["node"] is node From python-checkins at python.org Thu Apr 12 05:02:12 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 05:02:12 +0200 (CEST) Subject: [Python-checkins] r54769 - sandbox/trunk/2to3/fixes/fix_except.py Message-ID: <20070412030212.028641E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 05:02:04 2007 New Revision: 54769 Modified: sandbox/trunk/2to3/fixes/fix_except.py Log: Refactor to use the Name() macro. Modified: sandbox/trunk/2to3/fixes/fix_except.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_except.py (original) +++ sandbox/trunk/2to3/fixes/fix_except.py Thu Apr 12 05:02:04 2007 @@ -33,10 +33,6 @@ if n.children[0].value == 'except': yield (n, nodes[i+2]) -### Common across all transforms -as_leaf = pytree.Leaf(token.NAME, "as") -as_leaf.set_prefix(" ") - class FixExcept(basefix.BaseFix): PATTERN = """ @@ -55,7 +51,8 @@ for except_clause, e_suite in find_excepts(try_cleanup): if len(except_clause.children) == 4: (E, comma, N) = except_clause.children[1:4] - comma.replace(as_leaf.clone()) + comma.replace(Name("as", prefix=" ")) + if N.type != token.NAME: # Generate a new N for the except clause new_N = Name(self.new_name(), prefix=" ") From python-checkins at python.org Thu Apr 12 05:30:27 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 05:30:27 +0200 (CEST) Subject: [Python-checkins] r54770 - sandbox/trunk/2to3/fixes/fix_raw_input.py Message-ID: <20070412033027.E49B91E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 05:30:26 2007 New Revision: 54770 Modified: sandbox/trunk/2to3/fixes/fix_raw_input.py Log: Reindent, reformat for readability. Also, remove an unneeded import. Modified: sandbox/trunk/2to3/fixes/fix_raw_input.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_raw_input.py (original) +++ sandbox/trunk/2to3/fixes/fix_raw_input.py Thu Apr 12 05:30:26 2007 @@ -3,23 +3,19 @@ # Local imports import pytree -from pgen2 import token from fixes import basefix from fixes.util import Name class FixRawInput(basefix.BaseFix): PATTERN = """ - power< - 'raw_input' - args=trailer< '(' [any] ')' > - > - """ + power< 'raw_input' args=trailer< '(' [any] ')' > > + """ def transform(self, node): results = self.match(node) args = results["args"] - new = pytree.Node(self.syms.power, - [Name("input"), args.clone()]) + + new = pytree.Node(self.syms.power, [Name("input"), args.clone()]) new.set_prefix(node.get_prefix()) return new From python-checkins at python.org Thu Apr 12 05:34:43 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 05:34:43 +0200 (CEST) Subject: [Python-checkins] r54771 - sandbox/trunk/2to3/fixes/fix_repr.py Message-ID: <20070412033443.42AA51E4010@bag.python.org> Author: collin.winter Date: Thu Apr 12 05:34:39 2007 New Revision: 54771 Modified: sandbox/trunk/2to3/fixes/fix_repr.py Log: Reindent, reformat for readability. Also, remove an unneeded import. Modified: sandbox/trunk/2to3/fixes/fix_repr.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_repr.py (original) +++ sandbox/trunk/2to3/fixes/fix_repr.py Thu Apr 12 05:34:39 2007 @@ -5,7 +5,6 @@ # Local imports import pytree -from pgen2 import token from fixes import basefix from fixes.util import Call, Name @@ -13,15 +12,16 @@ class FixRepr(basefix.BaseFix): PATTERN = """ - atom < '`' expr=any '`' > - """ + atom < '`' expr=any '`' > + """ def transform(self, node): results = self.match(node) assert results expr = results["expr"].clone() + if expr.type == self.syms.testlist1: - expr = self.parenthesize(expr) + expr = self.parenthesize(expr) new = Call(Name("repr"), [expr]) new.set_prefix(node.get_prefix()) return new From python-checkins at python.org Thu Apr 12 06:10:04 2007 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Apr 2007 06:10:04 +0200 (CEST) Subject: [Python-checkins] r54772 - in python/trunk: Doc/lib/libstdtypes.tex Doc/lib/libstring.tex Lib/string.py Lib/test/string_tests.py Misc/NEWS Objects/stringobject.c Message-ID: <20070412041004.2B4291E4002@bag.python.org> Author: raymond.hettinger Date: Thu Apr 12 06:10:00 2007 New Revision: 54772 Modified: python/trunk/Doc/lib/libstdtypes.tex python/trunk/Doc/lib/libstring.tex python/trunk/Lib/string.py python/trunk/Lib/test/string_tests.py python/trunk/Misc/NEWS python/trunk/Objects/stringobject.c Log: SF 1193128: Let str.translate(None) be an identity transformation Modified: python/trunk/Doc/lib/libstdtypes.tex ============================================================================== --- python/trunk/Doc/lib/libstdtypes.tex (original) +++ python/trunk/Doc/lib/libstdtypes.tex Thu Apr 12 06:10:00 2007 @@ -878,6 +878,13 @@ You can use the \function{maketrans()} helper function in the \refmodule{string} module to create a translation table. +For string objects, set the \var{table} argument to \code{None} +for translations that only delete characters: +\begin{verbatim} + >>> 'read this short text'.translate(None, 'aeiou') + 'rd ths shrt txt' +\end{verbatim} +\versionadded[Support for a \code{None} \var{table} argument]{2.6} For Unicode objects, the \method{translate()} method does not accept the optional \var{deletechars} argument. Instead, it Modified: python/trunk/Doc/lib/libstring.tex ============================================================================== --- python/trunk/Doc/lib/libstring.tex (original) +++ python/trunk/Doc/lib/libstring.tex Thu Apr 12 06:10:00 2007 @@ -419,7 +419,8 @@ Delete all characters from \var{s} that are in \var{deletechars} (if present), and then translate the characters using \var{table}, which must be a 256-character string giving the translation for each - character value, indexed by its ordinal. + character value, indexed by its ordinal. If \var{table} is \code{None}, + then only the character deletion step is performed. \end{funcdesc} \begin{funcdesc}{upper}{s} Modified: python/trunk/Lib/string.py ============================================================================== --- python/trunk/Lib/string.py (original) +++ python/trunk/Lib/string.py Thu Apr 12 06:10:00 2007 @@ -487,7 +487,7 @@ deletions argument is not allowed for Unicode strings. """ - if deletions: + if deletions or table is None: return s.translate(table, deletions) else: # Add s[:0] so that if s is Unicode and table is an 8-bit string, Modified: python/trunk/Lib/test/string_tests.py ============================================================================== --- python/trunk/Lib/test/string_tests.py (original) +++ python/trunk/Lib/test/string_tests.py Thu Apr 12 06:10:00 2007 @@ -1096,6 +1096,9 @@ self.checkequal('Abc', 'abc', 'translate', table) self.checkequal('xyz', 'xyz', 'translate', table) self.checkequal('yz', 'xyz', 'translate', table, 'x') + self.checkequal('yx', 'zyzzx', 'translate', None, 'z') + self.checkequal('zyzzx', 'zyzzx', 'translate', None, '') + self.checkequal('zyzzx', 'zyzzx', 'translate', None) self.checkraises(ValueError, 'xyz', 'translate', 'too short', 'strip') self.checkraises(ValueError, 'xyz', 'translate', 'too short') Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Thu Apr 12 06:10:00 2007 @@ -14,6 +14,10 @@ - Request #1191699: Slices can now be pickled. +- Request #1193128: str.translate() now allows a None argument for + translations that only remove characters without re-mapping the + remaining characters. + - Patch #1682205: a TypeError while unpacking an iterable is no longer masked by a generic one with the message "unpack non-sequence". Modified: python/trunk/Objects/stringobject.c ============================================================================== --- python/trunk/Objects/stringobject.c (original) +++ python/trunk/Objects/stringobject.c Thu Apr 12 06:10:00 2007 @@ -2344,10 +2344,10 @@ string_translate(PyStringObject *self, PyObject *args) { register char *input, *output; - register const char *table; + const char *table; register Py_ssize_t i, c, changed = 0; PyObject *input_obj = (PyObject*)self; - const char *table1, *output_start, *del_table=NULL; + const char *output_start, *del_table=NULL; Py_ssize_t inlen, tablen, dellen = 0; PyObject *result; int trans_table[256]; @@ -2358,9 +2358,13 @@ return NULL; if (PyString_Check(tableobj)) { - table1 = PyString_AS_STRING(tableobj); + table = PyString_AS_STRING(tableobj); tablen = PyString_GET_SIZE(tableobj); } + else if (tableobj == Py_None) { + table = NULL; + tablen = 256; + } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(tableobj)) { /* Unicode .translate() does not support the deletechars @@ -2374,7 +2378,7 @@ return PyUnicode_Translate((PyObject *)self, tableobj, NULL); } #endif - else if (PyObject_AsCharBuffer(tableobj, &table1, &tablen)) + else if (PyObject_AsCharBuffer(tableobj, &table, &tablen)) return NULL; if (tablen != 256) { @@ -2403,7 +2407,6 @@ dellen = 0; } - table = table1; inlen = PyString_GET_SIZE(input_obj); result = PyString_FromStringAndSize((char *)NULL, inlen); if (result == NULL) @@ -2411,7 +2414,7 @@ output_start = output = PyString_AsString(result); input = PyString_AS_STRING(input_obj); - if (dellen == 0) { + if (dellen == 0 && table != NULL) { /* If no deletions are required, use faster code */ for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); @@ -2425,8 +2428,13 @@ return input_obj; } - for (i = 0; i < 256; i++) - trans_table[i] = Py_CHARMASK(table[i]); + if (table == NULL) { + for (i = 0; i < 256; i++) + trans_table[i] = Py_CHARMASK(i); + } else { + for (i = 0; i < 256; i++) + trans_table[i] = Py_CHARMASK(table[i]); + } for (i = 0; i < dellen; i++) trans_table[(int) Py_CHARMASK(del_table[i])] = -1; From python-checkins at python.org Thu Apr 12 06:16:34 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Apr 2007 06:16:34 +0200 (CEST) Subject: [Python-checkins] r54773 - sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py sandbox/trunk/pep0/test_pep0.py Message-ID: <20070412041634.08A541E4002@bag.python.org> Author: brett.cannon Date: Thu Apr 12 06:16:33 2007 New Revision: 54773 Modified: sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py sandbox/trunk/pep0/test_pep0.py Log: Fix author parsing (really need to have a consistent way of listing authors). Also updated TODO list of what is left to do. Minor bug in running pep0.py with a directory argument also fixed. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Thu Apr 12 06:16:33 2007 @@ -1,20 +1,43 @@ -In script: +Current discrepencies +--------------------- + * Author issues + Missing an author - - 207 - - 208 - - 209 - - 218 - - 228 - - 234 - - 238 - - 246 - - 251 - - 263 - - 312 - 314 + How to handle suffixes (Jr., etc.)? -* Read PEPs as UTF-8, not ASCII. + - 160 + - 205 +* Type/status issues: + - 160: missing F + - 206: missing W + - 216: missing R + - 220: missing D + - 226: missing F + - 247: missing F + - 248: missing F + - 249: missing F + - 251: missing F + - 269: added D + - 272: missing F + - 283: missing F + - 286: added A + - 320: missing F + - 344: added A + - 353: used F, expected A + - 356: missing F + - 364: added A + - 3102: used A, expected F + - 3104: used A, expected F + - 3107: used A, expected F + - 3104: used A +* Title are too long (use ellipsis?): + - 311 + - 3001 + + +Functionality to add +-------------------- + * Output static text for PEP 0. + Store Owners list in a data structure. - Support nicknames for PEP listing (e.g., "Guido van Rossum" -> @@ -28,11 +51,14 @@ - Would allow for easy validation that metadata is correct in PEPs. * Output PEP 0 with numerical PEP index. * Output PEP 0 with special sections. +* Make sure that it is easy to identify which PEP triggered an error. + -For PEPs: +To clean up PEPs +---------------- * Define (and enforce) consistency in Author field. * Empty PEPs are not in any way identified within the PEPs themselves. - + Get ride of section and just consider rejected? + + Get rid of section and just consider rejected? - No longer accept empty PEPs, right? * Meta-PEPs are not noted as such within the PEPs. + Add a "Meta" option for "Type"? Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Thu Apr 12 06:16:33 2007 @@ -1,6 +1,7 @@ """Auto-generate PEP 0 (PEP index). """ from __future__ import with_statement import os +import re def consume_headers(directory='.'): """Pull out metadata for every PEP in the specified directory and return @@ -61,15 +62,20 @@ def handle_author(data): """Return a list of author names.""" - if '<' in data: - author, email = data.split('<', 1) - elif '(' in data: - email, author = data.split('(', 1) - author = author[:author.index(')')] - else: - author = data - return [author_name.strip() for author_name in author.split(',') if - author_name] + angled = r'(?P.+?) <.+?>' + paren = r'.+? \((?P.+?)\)' + simple = r'(?P[^,]+)' + authors = [] + for regex in (angled, paren, simple): + # Watch out for commas separating multiple names. + regex += '(,\s+)?' + for match in re.finditer(regex, data): + authors.append(match.group('author')) + else: + # If authors were found then stop searching. + if authors: + break + return authors def handle_csv(data): """Handle the Post-History.""" @@ -143,7 +149,7 @@ else: path = argv[1] if os.path.isdir(path): - peps = consume_headers(directory) + peps = consume_headers(path) else: peps = [consume_pep(path)] Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Thu Apr 12 06:16:33 2007 @@ -41,12 +41,14 @@ for format in formats: rep = format % authors[0] expect = authors[0:1] - self.failUnlessEqual(pep0.handle_author(rep), expect) - rep += ',' + got = pep0.handle_author(rep) + self.failUnlessEqual(got, expect, + "%r failed; %r != %r" % (rep, got, expect)) + rep += ', ' self.failUnlessEqual(pep0.handle_author(rep), expect) rep += format % authors[1] self.failUnlessEqual(pep0.handle_author(rep), authors) - rep += ',' + rep += ', ' self.failUnlessEqual(pep0.handle_author(rep), authors) From buildbot at python.org Thu Apr 12 06:33:31 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Apr 2007 04:33:31 +0000 Subject: [Python-checkins] buildbot warnings in x86 gentoo trunk Message-ID: <20070412043332.1D76F1E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520gentoo%2520trunk/builds/2134 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl,raymond.hettinger Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_urllib2net make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Apr 12 07:34:30 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 07:34:30 +0200 (CEST) Subject: [Python-checkins] r54775 - sandbox/trunk/2to3/fixes/util.py Message-ID: <20070412053430.9073E1E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 07:34:30 2007 New Revision: 54775 Modified: sandbox/trunk/2to3/fixes/util.py Log: Add reversed() for 2.3-compat. Modified: sandbox/trunk/2to3/fixes/util.py ============================================================================== --- sandbox/trunk/2to3/fixes/util.py (original) +++ sandbox/trunk/2to3/fixes/util.py Thu Apr 12 07:34:30 2007 @@ -117,6 +117,12 @@ set = set except NameError: from sets import Set as set + +try: + reversed = reversed +except NameError: + def reversed(l): + return l[::-1] ########################################################### ### The following functions are to find bindings in a suite From python-checkins at python.org Thu Apr 12 07:35:32 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 07:35:32 +0200 (CEST) Subject: [Python-checkins] r54776 - sandbox/trunk/2to3/fixes/fix_except.py Message-ID: <20070412053532.9D9111E4004@bag.python.org> Author: collin.winter Date: Thu Apr 12 07:35:31 2007 New Revision: 54776 Modified: sandbox/trunk/2to3/fixes/fix_except.py Log: Refactoring/cleanup to use the new Node.insert_child() method. Modified: sandbox/trunk/2to3/fixes/fix_except.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_except.py (original) +++ sandbox/trunk/2to3/fixes/fix_except.py Thu Apr 12 07:35:31 2007 @@ -25,7 +25,7 @@ import pytree from pgen2 import token from fixes import basefix -from fixes.util import Assign, Attr, Name, is_tuple, is_list +from fixes.util import Assign, Attr, Name, is_tuple, is_list, reversed def find_excepts(nodes): for i, n in enumerate(nodes): @@ -76,9 +76,10 @@ else: assign = Assign(target, new_N) - assign.parent = e_suite - suite_stmts = suite_stmts[:i] + [assign] + suite_stmts - e_suite.children = suite_stmts + #XXX(cwinter) stopgap until children becomes a smart list + for child in reversed(suite_stmts[:i]): + e_suite.insert_child(0, child) + e_suite.insert_child(i, assign) children = [c.clone() for c in node.children[:3]] + try_cleanup return pytree.Node(node.type, children) From python-checkins at python.org Thu Apr 12 07:44:54 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 07:44:54 +0200 (CEST) Subject: [Python-checkins] r54778 - sandbox/trunk/2to3/fixes/fix_exec.py Message-ID: <20070412054454.6CF191E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 07:44:54 2007 New Revision: 54778 Modified: sandbox/trunk/2to3/fixes/fix_exec.py Log: Remove an unneeded import from fix_exec. Modified: sandbox/trunk/2to3/fixes/fix_exec.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_exec.py (original) +++ sandbox/trunk/2to3/fixes/fix_exec.py Thu Apr 12 07:44:54 2007 @@ -11,7 +11,6 @@ # Local imports import pytree -from pgen2 import token from fixes import basefix from fixes.util import Comma, Name, Call From python-checkins at python.org Thu Apr 12 07:46:36 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 07:46:36 +0200 (CEST) Subject: [Python-checkins] r54779 - sandbox/trunk/2to3/fixes/fix_input.py Message-ID: <20070412054636.177201E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 07:46:34 2007 New Revision: 54779 Modified: sandbox/trunk/2to3/fixes/fix_input.py Log: Remove unneeded imports from fix_input. Modified: sandbox/trunk/2to3/fixes/fix_input.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_input.py (original) +++ sandbox/trunk/2to3/fixes/fix_input.py Thu Apr 12 07:46:34 2007 @@ -2,9 +2,6 @@ # Author: Andre Roberge # Local imports -import pytree -import patcomp -from pgen2 import token from fixes import basefix from fixes.util import Call, Name From python-checkins at python.org Thu Apr 12 07:48:11 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 07:48:11 +0200 (CEST) Subject: [Python-checkins] r54780 - sandbox/trunk/2to3/fixes/fix_intern.py Message-ID: <20070412054811.B10741E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 07:48:10 2007 New Revision: 54780 Modified: sandbox/trunk/2to3/fixes/fix_intern.py Log: Remove an unneeded import from fix_intern. Modified: sandbox/trunk/2to3/fixes/fix_intern.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_intern.py (original) +++ sandbox/trunk/2to3/fixes/fix_intern.py Thu Apr 12 07:48:10 2007 @@ -7,7 +7,6 @@ # Local imports import pytree -from pgen2 import token from fixes import basefix from fixes.util import Name, Attr From python-checkins at python.org Thu Apr 12 07:55:09 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 07:55:09 +0200 (CEST) Subject: [Python-checkins] r54781 - sandbox/trunk/2to3/fixes/fix_long.py sandbox/trunk/2to3/fixes/fix_nonzero.py sandbox/trunk/2to3/fixes/fix_numliterals.py sandbox/trunk/2to3/fixes/fix_repr.py sandbox/trunk/2to3/fixes/fix_sysexcinfo.py Message-ID: <20070412055509.325191E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 07:55:08 2007 New Revision: 54781 Modified: sandbox/trunk/2to3/fixes/fix_long.py sandbox/trunk/2to3/fixes/fix_nonzero.py sandbox/trunk/2to3/fixes/fix_numliterals.py sandbox/trunk/2to3/fixes/fix_repr.py sandbox/trunk/2to3/fixes/fix_sysexcinfo.py Log: Remove unneeded imports from a number of fixers. Modified: sandbox/trunk/2to3/fixes/fix_long.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_long.py (original) +++ sandbox/trunk/2to3/fixes/fix_long.py Thu Apr 12 07:55:08 2007 @@ -8,7 +8,6 @@ # Local imports import pytree -from pgen2 import token from fixes import basefix from fixes.util import Name, Number Modified: sandbox/trunk/2to3/fixes/fix_nonzero.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_nonzero.py (original) +++ sandbox/trunk/2to3/fixes/fix_nonzero.py Thu Apr 12 07:55:08 2007 @@ -2,8 +2,6 @@ # Author: Collin Winter # Local imports -import pytree -from pgen2 import token from fixes import basefix from fixes.util import Name, syms Modified: sandbox/trunk/2to3/fixes/fix_numliterals.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_numliterals.py (original) +++ sandbox/trunk/2to3/fixes/fix_numliterals.py Thu Apr 12 07:55:08 2007 @@ -5,7 +5,6 @@ # Licensed to PSF under a Contributor Agreement. # Local imports -import pytree from pgen2 import token from fixes import basefix from fixes.util import Number, set Modified: sandbox/trunk/2to3/fixes/fix_repr.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_repr.py (original) +++ sandbox/trunk/2to3/fixes/fix_repr.py Thu Apr 12 07:55:08 2007 @@ -4,7 +4,6 @@ """Fixer that transforms `xyzzy` into repr(xyzzy).""" # Local imports -import pytree from fixes import basefix from fixes.util import Call, Name Modified: sandbox/trunk/2to3/fixes/fix_sysexcinfo.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_sysexcinfo.py (original) +++ sandbox/trunk/2to3/fixes/fix_sysexcinfo.py Thu Apr 12 07:55:08 2007 @@ -2,7 +2,6 @@ # Author: Collin Winter # Local imports -from pgen2 import token from pytree import Leaf from fixes import basefix From python-checkins at python.org Thu Apr 12 08:03:33 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 08:03:33 +0200 (CEST) Subject: [Python-checkins] r54782 - sandbox/trunk/2to3/fixes/fix_tuple_params.py Message-ID: <20070412060333.0C3251E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 08:03:32 2007 New Revision: 54782 Modified: sandbox/trunk/2to3/fixes/fix_tuple_params.py Log: Cleanup to reflect that node.children is now a list. Modified: sandbox/trunk/2to3/fixes/fix_tuple_params.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_tuple_params.py (original) +++ sandbox/trunk/2to3/fixes/fix_tuple_params.py Thu Apr 12 08:03:32 2007 @@ -88,11 +88,9 @@ new_lines[0].set_prefix(indent) after = start + 1 - children = list(suite[0].children) - children[after:after] = new_lines + suite[0].children[after:after] = new_lines for i in range(after+1, after+len(new_lines)+1): - children[i].set_prefix(indent) - suite[0].children = tuple(children) + suite[0].children[i].set_prefix(indent) suite[0].changed() def transform_lambda(self, node): From python-checkins at python.org Thu Apr 12 08:05:37 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 08:05:37 +0200 (CEST) Subject: [Python-checkins] r54783 - sandbox/trunk/2to3/fixes/fix_except.py sandbox/trunk/2to3/fixes/fix_tuple_params.py Message-ID: <20070412060537.B44631E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 08:05:37 2007 New Revision: 54783 Modified: sandbox/trunk/2to3/fixes/fix_except.py sandbox/trunk/2to3/fixes/fix_tuple_params.py Log: Add a bunch of TODO points. Modified: sandbox/trunk/2to3/fixes/fix_except.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_except.py (original) +++ sandbox/trunk/2to3/fixes/fix_except.py Thu Apr 12 08:05:37 2007 @@ -64,6 +64,7 @@ # Insert "old_N = new_N" as the first statement in # the except body. This loop skips leading whitespace # and indents + #TODO(cwinter) suite-cleanup suite_stmts = e_suite.children for i, stmt in enumerate(suite_stmts): if isinstance(stmt, pytree.Node): @@ -76,10 +77,11 @@ else: assign = Assign(target, new_N) - #XXX(cwinter) stopgap until children becomes a smart list + #TODO(cwinter) stopgap until children becomes a smart list for child in reversed(suite_stmts[:i]): e_suite.insert_child(0, child) e_suite.insert_child(i, assign) + #TODO(cwinter) fix this when children becomes a smart list children = [c.clone() for c in node.children[:3]] + try_cleanup return pytree.Node(node.type, children) Modified: sandbox/trunk/2to3/fixes/fix_tuple_params.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_tuple_params.py (original) +++ sandbox/trunk/2to3/fixes/fix_tuple_params.py Thu Apr 12 08:05:37 2007 @@ -43,6 +43,7 @@ suite = results["suite"] args = results["args"] # This crap is so "def foo(...): x = 5; y = 7" is handled correctly. + # TODO(cwinter): suite-cleanup if suite[0].children[1].type == token.INDENT: start = 2 indent = suite[0].children[1].value @@ -78,9 +79,11 @@ return node # This isn't strictly necessary, but it plays nicely with other fixers. + # TODO(cwinter) get rid of this when children becomes a smart list for line in new_lines: line.parent = suite[0] + # TODO(cwinter) suite-cleanup after = start if start == 0: new_lines[0].set_prefix(" ") From python-checkins at python.org Thu Apr 12 09:01:21 2007 From: python-checkins at python.org (georg.brandl) Date: Thu, 12 Apr 2007 09:01:21 +0200 (CEST) Subject: [Python-checkins] r54784 - python/trunk/Lib/Bastion.py python/trunk/Lib/rexec.py Message-ID: <20070412070121.BE5461E4002@bag.python.org> Author: georg.brandl Date: Thu Apr 12 09:01:19 2007 New Revision: 54784 Modified: python/trunk/Lib/Bastion.py python/trunk/Lib/rexec.py Log: Patch #1698951: clarify deprecation message in rexec and Bastion Modified: python/trunk/Lib/Bastion.py ============================================================================== --- python/trunk/Lib/Bastion.py (original) +++ python/trunk/Lib/Bastion.py Thu Apr 12 09:01:19 2007 @@ -97,7 +97,7 @@ """ - raise RuntimeError, "This code is not secure in Python 2.2 and 2.3" + raise RuntimeError, "This code is not secure in Python 2.2 and later" # Note: we define *two* ad-hoc functions here, get1 and get2. # Both are intended to be called in the same way: get(name). Modified: python/trunk/Lib/rexec.py ============================================================================== --- python/trunk/Lib/rexec.py (original) +++ python/trunk/Lib/rexec.py Thu Apr 12 09:01:19 2007 @@ -181,7 +181,7 @@ """ - raise RuntimeError, "This code is not secure in Python 2.2 and 2.3" + raise RuntimeError, "This code is not secure in Python 2.2 and later" ihooks._Verbose.__init__(self, verbose) # XXX There's a circular reference here: From buildbot at python.org Thu Apr 12 09:09:01 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Apr 2007 07:09:01 +0000 Subject: [Python-checkins] buildbot failure in x86 XP trunk Message-ID: <20070412070901.738D51E4002@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/370 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Thu Apr 12 10:46:58 2007 From: python-checkins at python.org (ziga.seilnacht) Date: Thu, 12 Apr 2007 10:46:58 +0200 (CEST) Subject: [Python-checkins] r54785 - python/trunk/Lib/test/test_urllib.py Message-ID: <20070412084658.2E87E1E4008@bag.python.org> Author: ziga.seilnacht Date: Thu Apr 12 10:46:51 2007 New Revision: 54785 Modified: python/trunk/Lib/test/test_urllib.py Log: Patch #1695862: remove the cleanup code, now that Windows buildbots are green again. Modified: python/trunk/Lib/test/test_urllib.py ============================================================================== --- python/trunk/Lib/test/test_urllib.py (original) +++ python/trunk/Lib/test/test_urllib.py Thu Apr 12 10:46:51 2007 @@ -27,7 +27,6 @@ def setUp(self): """Setup of a temp file to use for testing""" self.text = "test_urllib: %s\n" % self.__class__.__name__ - test_support.unlink(test_support.TESTFN) FILE = file(test_support.TESTFN, 'wb') try: FILE.write(self.text) @@ -196,7 +195,6 @@ def test_copy(self): # Test that setting the filename argument works. second_temp = "%s.2" % test_support.TESTFN - test_support.unlink(second_temp) self.registerFileForCleanUp(second_temp) result = urllib.urlretrieve(self.constructLocalFileUrl( test_support.TESTFN), second_temp) @@ -221,7 +219,6 @@ self.assertEqual(count, count_holder[0]) count_holder[0] = count_holder[0] + 1 second_temp = "%s.2" % test_support.TESTFN - test_support.unlink(second_temp) self.registerFileForCleanUp(second_temp) urllib.urlretrieve(self.constructLocalFileUrl(test_support.TESTFN), second_temp, hooktester) @@ -547,20 +544,6 @@ def test_main(): - # cleanup old test dir on Windows buildbots - old_test_path = test_support.TESTFN + ".2" - if os.path.isdir(old_test_path): - for root, dirs, files in os.walk(old_test_path, topdown=False): - for name in files: - os.remove(os.path.join(root, name)) - for name in dirs: - dirname = os.path.join(root, name) - if not os.path.islink(dirname): - os.rmdir(dirname) - else: - os.remove(dirname) - os.rmdir(old_test_path) - test_support.run_unittest( urlopen_FileTests, urlopen_HttpTests, From buildbot at python.org Thu Apr 12 11:15:15 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Apr 2007 09:15:15 +0000 Subject: [Python-checkins] buildbot warnings in x86 W2k trunk Message-ID: <20070412091515.EE60A1E4003@bag.python.org> The Buildbot has detected a new failure of x86 W2k trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520W2k%2520trunk/builds/207 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: ziga.seilnacht Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_profile sincerely, -The Buildbot From buildbot at python.org Thu Apr 12 11:40:16 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Apr 2007 09:40:16 +0000 Subject: [Python-checkins] buildbot warnings in ia64 Ubuntu trunk trunk Message-ID: <20070412094016.A91B01E4011@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%2520Ubuntu%2520trunk%2520trunk/builds/580 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: ziga.seilnacht Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_ctypes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Apr 12 12:35:03 2007 From: python-checkins at python.org (walter.doerwald) Date: Thu, 12 Apr 2007 12:35:03 +0200 (CEST) Subject: [Python-checkins] r54786 - in python/trunk: Lib/encodings/utf_8_sig.py Lib/test/test_codecs.py Misc/NEWS Message-ID: <20070412103503.5964A1E4010@bag.python.org> Author: walter.doerwald Date: Thu Apr 12 12:35:00 2007 New Revision: 54786 Modified: python/trunk/Lib/encodings/utf_8_sig.py python/trunk/Lib/test/test_codecs.py python/trunk/Misc/NEWS Log: Fix utf-8-sig incremental decoder, which didn't recognise a BOM when the first chunk fed to the decoder started with a BOM, but was longer than 3 bytes. Modified: python/trunk/Lib/encodings/utf_8_sig.py ============================================================================== --- python/trunk/Lib/encodings/utf_8_sig.py (original) +++ python/trunk/Lib/encodings/utf_8_sig.py Thu Apr 12 12:35:00 2007 @@ -44,14 +44,19 @@ self.first = True def _buffer_decode(self, input, errors, final): - if self.first and codecs.BOM_UTF8.startswith(input): # might be a BOM + if self.first: if len(input) < 3: - # not enough data to decide if this really is a BOM - # => try again on the next call - return (u"", 0) - (output, consumed) = codecs.utf_8_decode(input[3:], errors, final) - self.first = False - return (output, consumed+3) + if codecs.BOM_UTF8.startswith(input): + # not enough data to decide if this really is a BOM + # => try again on the next call + return (u"", 0) + else: + self.first = None + else: + self.first = None + if input[:3] == codecs.BOM_UTF8: + (output, consumed) = codecs.utf_8_decode(input[3:], errors, final) + return (output, consumed+3) return codecs.utf_8_decode(input, errors, final) def reset(self): Modified: python/trunk/Lib/test/test_codecs.py ============================================================================== --- python/trunk/Lib/test/test_codecs.py (original) +++ python/trunk/Lib/test/test_codecs.py Thu Apr 12 12:35:00 2007 @@ -429,6 +429,11 @@ # SF bug #1601501: check that the codec works with a buffer unicode("\xef\xbb\xbf", "utf-8-sig") + def test_bom(self): + d = codecs.getincrementaldecoder("utf-8-sig")() + s = u"spam" + self.assertEqual(d.decode(s.encode("utf-8-sig")), s) + class EscapeDecodeTest(unittest.TestCase): def test_empty(self): self.assertEquals(codecs.escape_decode(""), ("", 0)) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Thu Apr 12 12:35:00 2007 @@ -591,6 +591,8 @@ - idle: Honor the "Cancel" action in the save dialog (Debian bug #299092). +- Fix utf-8-sig incremental decoder, which didn't recognise a BOM when the + first chunk fed to the decoder started with a BOM, but was longer than 3 bytes. Extension Modules ----------------- From buildbot at python.org Thu Apr 12 12:41:14 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Apr 2007 10:41:14 +0000 Subject: [Python-checkins] buildbot failure in x86 XP trunk Message-ID: <20070412104114.D96FC1E4011@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/372 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: walter.doerwald BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Thu Apr 12 18:09:36 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 18:09:36 +0200 (CEST) Subject: [Python-checkins] r54789 - sandbox/trunk/2to3/tests/pytree_idempotency.py Message-ID: <20070412160936.824171E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 18:09:31 2007 New Revision: 54789 Modified: sandbox/trunk/2to3/tests/pytree_idempotency.py Log: Import tests.support so the path gets fixed up. Modified: sandbox/trunk/2to3/tests/pytree_idempotency.py ============================================================================== --- sandbox/trunk/2to3/tests/pytree_idempotency.py (original) +++ sandbox/trunk/2to3/tests/pytree_idempotency.py Thu Apr 12 18:09:31 2007 @@ -6,16 +6,19 @@ __author__ = "Guido van Rossum " +# Support imports (need to be imported first) +import support + # Python imports import os import sys import logging +# Local imports +import pytree import pgen2 from pgen2 import driver -import pytree - logging.basicConfig() def main(): From python-checkins at python.org Thu Apr 12 18:11:33 2007 From: python-checkins at python.org (collin.winter) Date: Thu, 12 Apr 2007 18:11:33 +0200 (CEST) Subject: [Python-checkins] r54790 - sandbox/trunk/2to3/tests/pytree_idempotency.py Message-ID: <20070412161133.3D8A51E4002@bag.python.org> Author: collin.winter Date: Thu Apr 12 18:11:32 2007 New Revision: 54790 Modified: sandbox/trunk/2to3/tests/pytree_idempotency.py Log: Indentation fix. Modified: sandbox/trunk/2to3/tests/pytree_idempotency.py ============================================================================== --- sandbox/trunk/2to3/tests/pytree_idempotency.py (original) +++ sandbox/trunk/2to3/tests/pytree_idempotency.py Thu Apr 12 18:11:32 2007 @@ -28,9 +28,9 @@ fn = "example.py" tree = dr.parse_file(fn, debug=True) if not diff(fn, tree): - print "No diffs." + print "No diffs." if not sys.argv[1:]: - return # Pass a dummy argument to run the complete test suite below + return # Pass a dummy argument to run the complete test suite below problems = [] From python-checkins at python.org Thu Apr 12 23:29:31 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Apr 2007 23:29:31 +0200 (CEST) Subject: [Python-checkins] r54791 - sandbox/trunk/pep0/test_pep0.py Message-ID: <20070412212931.BAF761E4002@bag.python.org> Author: brett.cannon Date: Thu Apr 12 23:29:29 2007 New Revision: 54791 Modified: sandbox/trunk/pep0/test_pep0.py Log: Refactor author parsing test. Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Thu Apr 12 23:29:29 2007 @@ -32,24 +32,22 @@ (got, data, string_rep)) def test_handle_author(self): - # Handle the various ways authors can be specified: - # Name , - # email (name), - # Name. - authors = ["Guido van Rossum", "Brett Cannon"] + # Handle the various ways authors can be specified. + # Test needs to validate not just how the author's name can be written + # but also variations in people's names (e.g., 'van', 'Jr.', etc.). + authors = ["Guido van Rossum", "Brett Cannon", ] formats = ["%s ", "email (%s)", "%s"] for format in formats: - rep = format % authors[0] - expect = authors[0:1] - got = pep0.handle_author(rep) - self.failUnlessEqual(got, expect, - "%r failed; %r != %r" % (rep, got, expect)) - rep += ', ' - self.failUnlessEqual(pep0.handle_author(rep), expect) - rep += format % authors[1] - self.failUnlessEqual(pep0.handle_author(rep), authors) - rep += ', ' - self.failUnlessEqual(pep0.handle_author(rep), authors) + for author_count in range(len(authors)): + rep = ', '.join(format % author + for author in authors[:author_count+1]) + expect = authors[:author_count+1] + got = pep0.handle_author(rep) + self.failUnlessEqual(got, expect) + # Test with a trailing comma. + rep += ',' + got = pep0.handle_author(rep) + self.failUnlessEqual(got, expect) class ParseMetaDataTests(unittest.TestCase): From python-checkins at python.org Thu Apr 12 23:29:52 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Apr 2007 23:29:52 +0200 (CEST) Subject: [Python-checkins] r54792 - sandbox/trunk/pep0/TODO Message-ID: <20070412212952.7D63E1E4002@bag.python.org> Author: brett.cannon Date: Thu Apr 12 23:29:50 2007 New Revision: 54792 Modified: sandbox/trunk/pep0/TODO Log: Make sure that PEPs are read as UTF-8. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Thu Apr 12 23:29:50 2007 @@ -38,6 +38,7 @@ Functionality to add -------------------- +* Read PEPs as UTF-8. * Output static text for PEP 0. + Store Owners list in a data structure. - Support nicknames for PEP listing (e.g., "Guido van Rossum" -> From python-checkins at python.org Thu Apr 12 23:31:25 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Apr 2007 23:31:25 +0200 (CEST) Subject: [Python-checkins] r54793 - sandbox/trunk/pep0/test_pep0.py Message-ID: <20070412213125.693201E4003@bag.python.org> Author: brett.cannon Date: Thu Apr 12 23:31:24 2007 New Revision: 54793 Modified: sandbox/trunk/pep0/test_pep0.py Log: Add two more names two author test that can cause trouble. Author test now fails. Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Thu Apr 12 23:31:24 2007 @@ -35,7 +35,8 @@ # Handle the various ways authors can be specified. # Test needs to validate not just how the author's name can be written # but also variations in people's names (e.g., 'van', 'Jr.', etc.). - authors = ["Guido van Rossum", "Brett Cannon", ] + authors = ["Guido van Rossum", "Brett Cannon", "Fred L. Drake, Jr.", + "Aahz"] formats = ["%s ", "email (%s)", "%s"] for format in formats: for author_count in range(len(authors)): From python-checkins at python.org Thu Apr 12 23:38:14 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Apr 2007 23:38:14 +0200 (CEST) Subject: [Python-checkins] r54794 - sandbox/trunk/pep0/pep0.py Message-ID: <20070412213814.E53A11E4002@bag.python.org> Author: brett.cannon Date: Thu Apr 12 23:38:09 2007 New Revision: 54794 Modified: sandbox/trunk/pep0/pep0.py Log: Fix handling of names that end in 'Jr.' and such. Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Thu Apr 12 23:38:09 2007 @@ -70,7 +70,15 @@ # Watch out for commas separating multiple names. regex += '(,\s+)?' for match in re.finditer(regex, data): - authors.append(match.group('author')) + author = match.group('author') + # Watch out for suffixes like 'Jr.' when they are comma-separated + # from the name and thus cause issues when *all* names are only + # separated by commas. + author = match.group('author') + if not author.partition(' ')[1] and author.endswith('.'): + prev_author = authors.pop() + author = ', '.join([prev_author, author]) + authors.append(author) else: # If authors were found then stop searching. if authors: From python-checkins at python.org Thu Apr 12 23:59:42 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Apr 2007 23:59:42 +0200 (CEST) Subject: [Python-checkins] r54795 - sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py sandbox/trunk/pep0/test_pep0.py Message-ID: <20070412215942.8B2891E4008@bag.python.org> Author: brett.cannon Date: Thu Apr 12 23:59:40 2007 New Revision: 54795 Modified: sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py sandbox/trunk/pep0/test_pep0.py Log: Fix the finding of a person's last name. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Thu Apr 12 23:59:40 2007 @@ -1,12 +1,7 @@ Current discrepencies --------------------- +Compatibility with PEP numerical index only (no static text). -* Author issues - + Missing an author - - 314 - + How to handle suffixes (Jr., etc.)? - - 160 - - 205 * Type/status issues: - 160: missing F - 206: missing W @@ -30,10 +25,20 @@ - 3104: used A, expected F - 3107: used A, expected F - 3104: used A -* Title are too long (use ellipsis?): + +* Titles are too long (use ellipsis?): - 311 - 3001 +* Blank lines between spaces in count: + - 42/100 + - 160/200 + - Will be more than currently in index: + + 364/666 + + 666/754 + + 754/3000 + + 3002/3099 + Functionality to add -------------------- Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Thu Apr 12 23:59:40 2007 @@ -94,6 +94,27 @@ 'Post-History': handle_csv, } +def last_name(full_name): + """Find the last name of a full name. + + If no last name (e.g, 'Aahz') then return the full name. If there is a + leading, lowercase portion to the last name (e.g., 'van' or 'von') then + include it. If there is a suffix (e.g., 'Jr.') that is appended through a + comma, then drop the suffix. + + """ + no_suffix = full_name.partition(',')[0] + name_parts = no_suffix.split() + part_count = len(name_parts) + if part_count == 1 or part_count == 2: + return name_parts[-1] + else: + assert part_count > 2 + if name_parts[-2].islower(): + return ' '.join(name_parts[-2:]) + else: + return name_parts[-1] + def sort_peps(peps): """Sort PEPs into meta, informational, accepted, open, finished, empty, and essentially dead.""" @@ -133,18 +154,7 @@ number = str(pep['PEP']).rjust(4) title = pep['Title'] authors_list = [] - for author in pep['Author']: - name_parts = author.split() - last_name = name_parts.pop() - try: - last_name_leader = name_parts.pop() - except IndexError: - pass - else: - if last_name_leader[0].islower(): - last_name = '%s %s' % (last_name_leader, last_name) - authors_list.append(last_name) - authors = ', '.join(authors_list) + authors = ', '.join(last_name(author) for author in pep['Author']) output.write(" %s%s %s %s %s\n" % (type_abbr, status_abbr, number, title.ljust(44), authors)) Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Thu Apr 12 23:59:40 2007 @@ -1,7 +1,8 @@ from __future__ import with_statement +import pep0 + import unittest from test import test_support -import pep0 from contextlib import contextmanager import os @@ -142,34 +143,19 @@ self.failUnless('Post-History' in metadata) self.failUnlessEqual(metadata['Post-History'], dates) - def test_utf8(self): - # Need to handle text as UTF-8. - # XXX - pass - - -class PepSortTests(unittest.TestCase): - - def test_meta(self): - pass - - def test_info(self): - pass - - def test_accepted(self): - pass - - def test_open(self): - pass - - def test_finished(self): - pass - def test_empty(self): - pass +class OutputTests(unittest.TestCase): - def test_dead(self): - pass + def test_author_last_name(self): + # Test that last names are discovered properly. + test_names = [("Brett Cannon", "Cannon"), + ("Guido van Rossum", "van Rossum"), + ("Fred L. Drake, Jr.", "Drake"), + ("Aahz", "Aahz"), + ] + for full_name, expect in test_names: + got = pep0.last_name(full_name) + self.failUnlessEqual(got, expect) def test_main(): @@ -177,6 +163,7 @@ HandlerTests, ParseMetaDataTests, ConsumePepTests, + OutputTests, ) From python-checkins at python.org Fri Apr 13 00:08:54 2007 From: python-checkins at python.org (brett.cannon) Date: Fri, 13 Apr 2007 00:08:54 +0200 (CEST) Subject: [Python-checkins] r54796 - sandbox/trunk/pep0/TODO Message-ID: <20070412220854.2121C1E4002@bag.python.org> Author: brett.cannon Date: Fri Apr 13 00:08:50 2007 New Revision: 54796 Modified: sandbox/trunk/pep0/TODO Log: Clean up todo list. Separate out from discrepencies things that are from how the index has been handled and are definitely not the script's fault. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Fri Apr 13 00:08:50 2007 @@ -2,7 +2,7 @@ --------------------- Compatibility with PEP numerical index only (no static text). -* Type/status issues: +* Type/status issues (might be inconsistencies between index and PEP): - 160: missing F - 206: missing W - 216: missing R @@ -26,24 +26,12 @@ - 3107: used A, expected F - 3104: used A -* Titles are too long (use ellipsis?): - - 311 - - 3001 - -* Blank lines between spaces in count: - - 42/100 - - 160/200 - - Will be more than currently in index: - + 364/666 - + 666/754 - + 754/3000 - + 3002/3099 - Functionality to add -------------------- * Read PEPs as UTF-8. + * Output static text for PEP 0. + Store Owners list in a data structure. - Support nicknames for PEP listing (e.g., "Guido van Rossum" -> @@ -55,20 +43,49 @@ maintained and considered up-to-date? + Store Key in data structure for easy mapping? - Would allow for easy validation that metadata is correct in PEPs. + * Output PEP 0 with numerical PEP index. + * Output PEP 0 with special sections. + * Make sure that it is easy to identify which PEP triggered an error. + + Has all expected fields. + + Values in fields correct. + + Formatting correct. + - Plaintext. + - reST. -To clean up PEPs +Inconsistencies ---------------- -* Define (and enforce) consistency in Author field. +* Author field + + Three different formats for author (two include an email address). + + Best to settle on a single format. + - Author names separated by commas. + - Maintain email addresses only in PEP index so as to always have + up-to-date address in a single location. + +* Counting gap in numerical index and a newline. + + 42/100, 160/200. + + No other spaces in the count are used (e.g., 666/754). + + Have no spaces, always have a space? + + Should jumps in thousands digit have more than a single newline? + +* Titles that are longer than allowed. + + 311, 3001. + + Use custom titles to fit. + + Possible solutions. + - Use ellipsis to shorten name for index? + - Just deal with some being longer than expected? + * Empty PEPs are not in any way identified within the PEPs themselves. + Get rid of section and just consider rejected? - No longer accept empty PEPs, right? + * Meta-PEPs are not noted as such within the PEPs. + Add a "Meta" option for "Type"? -* Fix inconsistent usage of Status field. - + Some PEPs just say "Standard"; missing "Track". -* Informational, meta, and process PEPs inconsistently have status listed in - index. + +* Status field. + + Not all PEPs use consistent names (e.g., some just say "Standard" instead + of "Standard Track"). + + Status of PEPs not consistently listed in index. From python-checkins at python.org Fri Apr 13 06:16:21 2007 From: python-checkins at python.org (brett.cannon) Date: Fri, 13 Apr 2007 06:16:21 +0200 (CEST) Subject: [Python-checkins] r54803 - sandbox/trunk/pep0/pep0.py Message-ID: <20070413041621.2EC601E4005@bag.python.org> Author: brett.cannon Date: Fri Apr 13 06:16:15 2007 New Revision: 54803 Modified: sandbox/trunk/pep0/pep0.py Log: Do not suppress status output if the PEP is a process or informational PEP. Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Fri Apr 13 06:16:15 2007 @@ -147,7 +147,7 @@ """Write PEP info to 'output'.""" type_abbr = pep['Type'][0].upper() status = pep['Status'] - if status == 'Draft' or type_abbr in ('I', 'P'): + if status == 'Draft': status_abbr = ' ' else: status_abbr = status[0].upper() From python-checkins at python.org Fri Apr 13 06:17:15 2007 From: python-checkins at python.org (brett.cannon) Date: Fri, 13 Apr 2007 06:17:15 +0200 (CEST) Subject: [Python-checkins] r54804 - sandbox/trunk/pep0/TODO Message-ID: <20070413041715.84CB71E4002@bag.python.org> Author: brett.cannon Date: Fri Apr 13 06:17:12 2007 New Revision: 54804 Modified: sandbox/trunk/pep0/TODO Log: Reorganize TODO inconsistencies. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Fri Apr 13 06:17:12 2007 @@ -1,30 +1,10 @@ -Current discrepencies ---------------------- -Compatibility with PEP numerical index only (no static text). - -* Type/status issues (might be inconsistencies between index and PEP): - - 160: missing F - - 206: missing W - - 216: missing R - - 220: missing D - - 226: missing F - - 247: missing F - - 248: missing F - - 249: missing F - - 251: missing F - - 269: added D - - 272: missing F - - 283: missing F - - 286: added A - - 320: missing F - - 344: added A - - 353: used F, expected A - - 356: missing F - - 364: added A - - 3102: used A, expected F - - 3104: used A, expected F - - 3107: used A, expected F - - 3104: used A +Current discrepencies/bugs +-------------------------- + +* Be able to import authors.py . + - Probably as simple as declaring encoding. + - Otherwise prepend 'u' to every string. + Functionality to add @@ -51,6 +31,9 @@ * Make sure that it is easy to identify which PEP triggered an error. + Has all expected fields. + Values in fields correct. + - Type + - Status + - All authors declared in authors.py. + Formatting correct. - Plaintext. - reST. @@ -58,34 +41,38 @@ Inconsistencies ---------------- -* Author field - + Three different formats for author (two include an email address). - + Best to settle on a single format. - - Author names separated by commas. - - Maintain email addresses only in PEP index so as to always have - up-to-date address in a single location. - -* Counting gap in numerical index and a newline. - + 42/100, 160/200. - + No other spaces in the count are used (e.g., 666/754). - + Have no spaces, always have a space? - + Should jumps in thousands digit have more than a single newline? - -* Titles that are longer than allowed. - + 311, 3001. - + Use custom titles to fit. - + Possible solutions. - - Use ellipsis to shorten name for index? - - Just deal with some being longer than expected? - -* Empty PEPs are not in any way identified within the PEPs themselves. - + Get rid of section and just consider rejected? - - No longer accept empty PEPs, right? - -* Meta-PEPs are not noted as such within the PEPs. - + Add a "Meta" option for "Type"? - -* Status field. - + Not all PEPs use consistent names (e.g., some just say "Standard" instead - of "Standard Track"). - + Status of PEPs not consistently listed in index. +* Within PEPs: + + + Author field + - Three different formats for author (two include an email address). + - Best to settle on a single format. + * Author names separated by commas. + * Maintain email addresses only in PEP index so as to always have + up-to-date address in a single location. + + + Type field + - Meta-PEPs are not delineated as such. + + + Status field. + - Not all PEPs use consistent names (e.g., some just say "Standard" instead + of "Standard Track"). + - Empty PEPs are not specified as such. + +* In the index: + + * Counting gap in numerical index and a newline. + + 42/100, 160/200. + + No other spaces in the count are used (e.g., 666/754). + + Have no spaces, always have a space? + + Should jumps in thousands digit have more than a single newline? + + * Titles that are longer than allowed. + + 311, 3001. + + Use custom titles to fit. + + Possible solutions. + - Use ellipsis to shorten name for index? + - Just deal with some being longer than expected? + + * Type/Status field. + + Informational PEPs inconsistenty leave out Status. + From python-checkins at python.org Fri Apr 13 18:12:05 2007 From: python-checkins at python.org (barry.warsaw) Date: Fri, 13 Apr 2007 18:12:05 +0200 (CEST) Subject: [Python-checkins] r54805 - python/branches/release25-maint/Lib/test/test_pty.py Message-ID: <20070413161205.4BA581E4002@bag.python.org> Author: barry.warsaw Date: Fri Apr 13 18:12:02 2007 New Revision: 54805 Modified: python/branches/release25-maint/Lib/test/test_pty.py Log: Add code to read from master_fd in the parent, breaking when we get an OSError (EIO can occur on Linux) or there's no more data to read. Without this, test_pty.py can hang on the waitpid() because the child is blocking on the stdout write. This will definitely happen on Mac OS X and could potentially happen on other platforms. See the comment for details. Modified: python/branches/release25-maint/Lib/test/test_pty.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_pty.py (original) +++ python/branches/release25-maint/Lib/test/test_pty.py Fri Apr 13 18:12:02 2007 @@ -115,6 +115,24 @@ os._exit(4) else: debug("Waiting for child (%d) to finish."%pid) + # In verbose mode, we have to consume the debug output from the child or + # the child will block, causing this test to hang in the parent's + # waitpid() call. The child blocks after a platform-dependent amount of + # data is written to its fd. On Linux 2.6, it's 4000 bytes and the child + # won't block, but on OS X even the small writes in the child above will + # block it. Also on Linux, the read() will throw an OSError (input/output + # error) when it tries to read past the end of the buffer but the child's + # already exited, so catch and discard those exceptions. It's not worth + # checking for EIO. + while True: + try: + data = os.read(master_fd, 80) + except OSError: + break + if not data: + break + sys.stdout.write(data.replace('\r\n', '\n')) + ##line = os.read(master_fd, 80) ##lines = line.replace('\r\n', '\n').split('\n') ##if False and lines != ['In child, calling os.setsid()', From python at rcn.com Fri Apr 13 18:43:13 2007 From: python at rcn.com (Raymond Hettinger) Date: Fri, 13 Apr 2007 12:43:13 -0400 (EDT) Subject: [Python-checkins] r54805 - python/branches/release25-maint/Lib/test/test_pty.py Message-ID: <20070413124313.BFJ16741@ms09.lnh.mail.rcn.net> I thought the 25 maint branch was closed until a few days after the release-candidate goes final. If it is open, let me know, I've got more fixes to apply. Raymond From barry at python.org Fri Apr 13 18:54:33 2007 From: barry at python.org (Barry Warsaw) Date: Fri, 13 Apr 2007 12:54:33 -0400 Subject: [Python-checkins] r54805 - python/branches/release25-maint/Lib/test/test_pty.py In-Reply-To: <20070413124313.BFJ16741@ms09.lnh.mail.rcn.net> References: <20070413124313.BFJ16741@ms09.lnh.mail.rcn.net> Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Apr 13, 2007, at 12:43 PM, Raymond Hettinger wrote: > I thought the 25 maint branch was closed until a few days after the > release-candidate goes final. If it is open, let me know, I've got > more fixes to apply. I don't know, maybe it is. This one's extremely low risk as it only affects certain platforms when test_pty is run verbosely. But if it ain't cool, I'll back it out and re-apply after 2.5.1 final. - -Barry -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Darwin) iQCVAwUBRh+1ynEjvBPtnXfVAQIZJQQAkMPMe4G9LyPUp9Tt2OmmIvIfdQiat/yS FeGvknxgQRITRZK7ByVZPp/FX6of65oPYkyprnBdxAfE36TYKt9nVzdYSQ1YIOOM RQaFczCuj/u07vnvSvBngoVUuGFW9MbAvtGT7nMwoFBZXPUjC5Q1hGXlo2/0jZg3 q85tNLXJ4d8= =Ywzx -----END PGP SIGNATURE----- From python-checkins at python.org Fri Apr 13 20:47:16 2007 From: python-checkins at python.org (barry.warsaw) Date: Fri, 13 Apr 2007 20:47:16 +0200 (CEST) Subject: [Python-checkins] r54807 - python/trunk/Lib/test/test_pty.py Message-ID: <20070413184716.C81AA1E4003@bag.python.org> Author: barry.warsaw Date: Fri Apr 13 20:47:14 2007 New Revision: 54807 Modified: python/trunk/Lib/test/test_pty.py Log: Port r54805 from python25-maint branch: Add code to read from master_fd in the parent, breaking when we get an OSError (EIO can occur on Linux) or there's no more data to read. Without this, test_pty.py can hang on the waitpid() because the child is blocking on the stdout write. This will definitely happen on Mac OS X and could potentially happen on other platforms. See the comment for details. Modified: python/trunk/Lib/test/test_pty.py ============================================================================== --- python/trunk/Lib/test/test_pty.py (original) +++ python/trunk/Lib/test/test_pty.py Fri Apr 13 20:47:14 2007 @@ -1,5 +1,6 @@ import pty import os +import sys import signal from test.test_support import verbose, TestSkipped, run_unittest import unittest @@ -120,6 +121,25 @@ os._exit(4) else: debug("Waiting for child (%d) to finish." % pid) + # In verbose mode, we have to consume the debug output from the + # child or the child will block, causing this test to hang in the + # parent's waitpid() call. The child blocks after a + # platform-dependent amount of data is written to its fd. On + # Linux 2.6, it's 4000 bytes and the child won't block, but on OS + # X even the small writes in the child above will block it. Also + # on Linux, the read() will throw an OSError (input/output error) + # when it tries to read past the end of the buffer but the child's + # already exited, so catch and discard those exceptions. It's not + # worth checking for EIO. + while True: + try: + data = os.read(master_fd, 80) + except OSError: + break + if not data: + break + sys.stdout.write(data.replace('\r\n', '\n')) + ##line = os.read(master_fd, 80) ##lines = line.replace('\r\n', '\n').split('\n') ##if False and lines != ['In child, calling os.setsid()', From martin at v.loewis.de Fri Apr 13 22:58:57 2007 From: martin at v.loewis.de (=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=) Date: Fri, 13 Apr 2007 22:58:57 +0200 Subject: [Python-checkins] r54805 - python/branches/release25-maint/Lib/test/test_pty.py In-Reply-To: References: <20070413124313.BFJ16741@ms09.lnh.mail.rcn.net> Message-ID: <461FEF11.4020100@v.loewis.de> > I don't know, maybe it is. This one's extremely low risk as it only > affects certain platforms when test_pty is run verbosely. But if it > ain't cool, I'll back it out and re-apply after 2.5.1 final. Please back it out. If there are changes to the branch, we would have to create another release candidate (IMO). Regards, Martin From python at rcn.com Fri Apr 13 23:34:47 2007 From: python at rcn.com (Raymond Hettinger) Date: Fri, 13 Apr 2007 17:34:47 -0400 (EDT) Subject: [Python-checkins] r54805 - python/branches/release25-maint/Lib/test/test_pty.py Message-ID: <20070413173447.BFK12886@ms09.lnh.mail.rcn.net> [MvL] > Please back it out. If there are changes to the branch, we would have > to create another release candidate (IMO). I believe Anthony had already tagged a branch. Barry's checkin was on the trunk so it may be automatically excluded from the final release. If so, then the only issue would be if the rc bad and we had to build a new one off of the trunk.. Raymond From martin at v.loewis.de Fri Apr 13 23:49:21 2007 From: martin at v.loewis.de (=?UTF-8?B?Ik1hcnRpbiB2LiBMw7Z3aXMi?=) Date: Fri, 13 Apr 2007 23:49:21 +0200 Subject: [Python-checkins] r54805 - python/branches/release25-maint/Lib/test/test_pty.py In-Reply-To: <20070413173447.BFK12886@ms09.lnh.mail.rcn.net> References: <20070413173447.BFK12886@ms09.lnh.mail.rcn.net> Message-ID: <461FFAE1.9090409@v.loewis.de> Raymond Hettinger schrieb: > [MvL] >> Please back it out. If there are changes to the branch, we would >> have to create another release candidate (IMO). > > I believe Anthony had already tagged a branch. Barry's checkin was > on the trunk so it may be automatically excluded from the final > release. If so, then the only issue would be if the rc bad and we had > to build a new one off of the trunk.. Barry's checkin was *not* on the trunk, but on the 2.5 branch: r54805 | barry.warsaw | 2007-04-13 18:12:02 +0200 (Fri, 13 Apr 2007) | 6 lines Changed paths: M /python/branches/release25-maint/Lib/test/test_pty.py Anthony did not recently create another branch, AFAICT: the last one was the release25-maint branch. Instead, he created a tag "r251c1". This tag will *not* be used to create the final 2.5.1 release. Instead, the final 2.5.1 release will be made out of the release25-maint branch. Hope this clears it up (and hoping this is all correct). Regards, Martin From python-checkins at python.org Sat Apr 14 00:02:51 2007 From: python-checkins at python.org (collin.winter) Date: Sat, 14 Apr 2007 00:02:51 +0200 (CEST) Subject: [Python-checkins] r54809 - sandbox/trunk/2to3/HACKING Message-ID: <20070413220251.700AE1E4003@bag.python.org> Author: collin.winter Date: Sat Apr 14 00:02:47 2007 New Revision: 54809 Modified: sandbox/trunk/2to3/HACKING Log: Add a section on more complicated modifications to 2to3. Modified: sandbox/trunk/2to3/HACKING ============================================================================== --- sandbox/trunk/2to3/HACKING (original) +++ sandbox/trunk/2to3/HACKING Sat Apr 14 00:02:47 2007 @@ -9,6 +9,22 @@ +Putting 2to3 to work somewhere else: + + * By default, 2to3 uses a merger of Python 2.x and Python 3's grammars. + If you want to support a different grammar, just replace the + Grammar.txt file with Grammar/Grammar from your chosen Python version. + + * The real heart of 2to3 is the concrete syntax tree parser in pgen2; this + chunk of the system is suitable for a wide range of applications that + require CST transformation. All that's required is to rip off the fixer + layer and replace it with something else that walks the tree. One + application would be a tool to check/enforce style guidelines; this + could leverage 90% of the existing infrastructure with primarily + cosmetic changes (e.g., fixes/fix_*.py -> styles/style_*.py). + + + TODO Simple: From python-checkins at python.org Sat Apr 14 00:03:38 2007 From: python-checkins at python.org (collin.winter) Date: Sat, 14 Apr 2007 00:03:38 +0200 (CEST) Subject: [Python-checkins] r54810 - in sandbox/trunk/2to3: pytree.py tests/test_pytree.py Message-ID: <20070413220338.B352D1E4003@bag.python.org> Author: collin.winter Date: Sat Apr 14 00:03:36 2007 New Revision: 54810 Modified: sandbox/trunk/2to3/pytree.py sandbox/trunk/2to3/tests/test_pytree.py Log: Add a get_next_sibling() method to pytree.Base. Modified: sandbox/trunk/2to3/pytree.py ============================================================================== --- sandbox/trunk/2to3/pytree.py (original) +++ sandbox/trunk/2to3/pytree.py Sat Apr 14 00:03:36 2007 @@ -142,6 +142,21 @@ del self.parent.children[i] self.parent = None return i + + def get_next_sibling(self): + """Return the node immediately following the invocant in their + parent's children list. If the invocant does not have a next + sibling, return None.""" + if self.parent is None: + return None + + # Can't use index(); we need to test by identity + for i, sibling in enumerate(self.parent.children): + if sibling is self: + try: + return self.parent.children[i+1] + except IndexError: + return None class Node(Base): Modified: sandbox/trunk/2to3/tests/test_pytree.py ============================================================================== --- sandbox/trunk/2to3/tests/test_pytree.py (original) +++ sandbox/trunk/2to3/tests/test_pytree.py Sat Apr 14 00:03:36 2007 @@ -262,6 +262,24 @@ # I don't care what it raises, so long as it's an exception self.assertRaises(Exception, n1.append_child, list) + + def testNodeNextSibling(self): + n1 = pytree.Node(1000, []) + n2 = pytree.Node(1000, []) + p1 = pytree.Node(1000, [n1, n2]) + + self.failUnless(n1.get_next_sibling() is n2) + self.assertEqual(n2.get_next_sibling(), None) + self.assertEqual(p1.get_next_sibling(), None) + + def testLeafNextSibling(self): + l1 = pytree.Leaf(100, "a") + l2 = pytree.Leaf(100, "b") + p1 = pytree.Node(1000, [l1, l2]) + + self.failUnless(l1.get_next_sibling() is l2) + self.assertEqual(l2.get_next_sibling(), None) + self.assertEqual(p1.get_next_sibling(), None) class TestPatterns(support.TestCase): From python-checkins at python.org Sat Apr 14 00:05:53 2007 From: python-checkins at python.org (collin.winter) Date: Sat, 14 Apr 2007 00:05:53 +0200 (CEST) Subject: [Python-checkins] r54811 - in sandbox/trunk/2to3: pytree.py tests/test_pytree.py Message-ID: <20070413220553.8F4161E4012@bag.python.org> Author: collin.winter Date: Sat Apr 14 00:05:51 2007 New Revision: 54811 Modified: sandbox/trunk/2to3/pytree.py sandbox/trunk/2to3/tests/test_pytree.py Log: Add a get_suffix() method to pytree.Base. Modified: sandbox/trunk/2to3/pytree.py ============================================================================== --- sandbox/trunk/2to3/pytree.py (original) +++ sandbox/trunk/2to3/pytree.py Sat Apr 14 00:05:51 2007 @@ -142,7 +142,7 @@ del self.parent.children[i] self.parent = None return i - + def get_next_sibling(self): """Return the node immediately following the invocant in their parent's children list. If the invocant does not have a next @@ -157,6 +157,14 @@ return self.parent.children[i+1] except IndexError: return None + + def get_suffix(self): + """Return the string immediately following the invocant node. This + is effectively equivalent to node.get_next_sibling().get_prefix()""" + next_sib = self.get_next_sibling() + if next_sib is None: + return "" + return next_sib.get_prefix() class Node(Base): Modified: sandbox/trunk/2to3/tests/test_pytree.py ============================================================================== --- sandbox/trunk/2to3/tests/test_pytree.py (original) +++ sandbox/trunk/2to3/tests/test_pytree.py Sat Apr 14 00:05:51 2007 @@ -99,6 +99,22 @@ self.assertEqual(n1.get_prefix(), " ") self.assertEqual(l1.get_prefix(), " ") + def testGetSuffix(self): + l1 = pytree.Leaf(100, "foo", prefix="a") + l2 = pytree.Leaf(100, "bar", prefix="b") + n1 = pytree.Node(1000, [l1, l2]) + + self.assertEqual(l1.get_suffix(), l2.get_prefix()) + self.assertEqual(l2.get_suffix(), "") + self.assertEqual(n1.get_suffix(), "") + + l3 = pytree.Leaf(100, "bar", prefix="c") + n2 = pytree.Node(1000, [n1, l3]) + + self.assertEqual(n1.get_suffix(), l3.get_prefix()) + self.assertEqual(l3.get_suffix(), "") + self.assertEqual(n2.get_suffix(), "") + def testNodeEq(self): n1 = pytree.Node(1000, ()) n2 = pytree.Node(1000, [], context=(" ", (1, 0))) From python-checkins at python.org Sat Apr 14 00:07:33 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Sat, 14 Apr 2007 00:07:33 +0200 (CEST) Subject: [Python-checkins] r54812 - in python/trunk: Objects/frameobject.c Python/ceval.c Message-ID: <20070413220733.F005F1E4016@bag.python.org> Author: kristjan.jonsson Date: Sat Apr 14 00:07:33 2007 New Revision: 54812 Modified: python/trunk/Objects/frameobject.c python/trunk/Python/ceval.c Log: Fix a bug when using the __lltrace__ opcode tracer, and a problem sith signed chars in frameobject.c which can occur with opcodes > 127 Modified: python/trunk/Objects/frameobject.c ============================================================================== --- python/trunk/Objects/frameobject.c (original) +++ python/trunk/Objects/frameobject.c Sat Apr 14 00:07:33 2007 @@ -68,7 +68,7 @@ int new_lineno = 0; /* The new value of f_lineno */ int new_lasti = 0; /* The new value of f_lasti */ int new_iblock = 0; /* The new value of f_iblock */ - char *code = NULL; /* The bytecode for the frame... */ + unsigned char *code = NULL; /* The bytecode for the frame... */ Py_ssize_t code_len = 0; /* ...and its length */ char *lnotab = NULL; /* Iterating over co_lnotab */ Py_ssize_t lnotab_len = 0; /* (ditto) */ @@ -85,7 +85,7 @@ int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */ int in_finally[CO_MAXBLOCKS]; /* (ditto) */ int blockstack_top = 0; /* (ditto) */ - int setup_op = 0; /* (ditto) */ + unsigned char setup_op = 0; /* (ditto) */ /* f_lineno must be an integer. */ if (!PyInt_Check(p_new_lineno)) { Modified: python/trunk/Python/ceval.c ============================================================================== --- python/trunk/Python/ceval.c (original) +++ python/trunk/Python/ceval.c Sat Apr 14 00:07:33 2007 @@ -662,7 +662,7 @@ #define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \ lltrace && prtrace(TOP(), "stackadj")); \ assert(STACK_LEVEL() <= co->co_stacksize); } -#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER)) +#define EXT_POP(STACK_POINTER) (lltrace && prtrace((STACK_POINTER)[-1], "ext_pop"), *--(STACK_POINTER)) #else #define PUSH(v) BASIC_PUSH(v) #define POP() BASIC_POP() From python-checkins at python.org Sat Apr 14 00:10:01 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Sat, 14 Apr 2007 00:10:01 +0200 (CEST) Subject: [Python-checkins] r54813 - in python/branches/release25-maint: Objects/frameobject.c Python/ceval.c Message-ID: <20070413221001.58AC31E4005@bag.python.org> Author: kristjan.jonsson Date: Sat Apr 14 00:09:59 2007 New Revision: 54813 Modified: python/branches/release25-maint/Objects/frameobject.c python/branches/release25-maint/Python/ceval.c Log: Fix a bug when using the __lltrace__ opcode tracer, and a problem sith signed chars in frameobject.c which can occur with opcodes > 127 Modified: python/branches/release25-maint/Objects/frameobject.c ============================================================================== --- python/branches/release25-maint/Objects/frameobject.c (original) +++ python/branches/release25-maint/Objects/frameobject.c Sat Apr 14 00:09:59 2007 @@ -68,7 +68,7 @@ int new_lineno = 0; /* The new value of f_lineno */ int new_lasti = 0; /* The new value of f_lasti */ int new_iblock = 0; /* The new value of f_iblock */ - char *code = NULL; /* The bytecode for the frame... */ + unsigned char *code = NULL; /* The bytecode for the frame... */ Py_ssize_t code_len = 0; /* ...and its length */ char *lnotab = NULL; /* Iterating over co_lnotab */ Py_ssize_t lnotab_len = 0; /* (ditto) */ @@ -85,7 +85,7 @@ int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */ int in_finally[CO_MAXBLOCKS]; /* (ditto) */ int blockstack_top = 0; /* (ditto) */ - int setup_op = 0; /* (ditto) */ + unsigned char setup_op = 0; /* (ditto) */ /* f_lineno must be an integer. */ if (!PyInt_Check(p_new_lineno)) { Modified: python/branches/release25-maint/Python/ceval.c ============================================================================== --- python/branches/release25-maint/Python/ceval.c (original) +++ python/branches/release25-maint/Python/ceval.c Sat Apr 14 00:09:59 2007 @@ -662,7 +662,7 @@ #define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \ lltrace && prtrace(TOP(), "stackadj")); \ assert(STACK_LEVEL() <= co->co_stacksize); } -#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER)) +#define EXT_POP(STACK_POINTER) (lltrace && prtrace((STACK_POINTER)[-1], "ext_pop"), *--(STACK_POINTER)) #else #define PUSH(v) BASIC_PUSH(v) #define POP() BASIC_POP() From python-checkins at python.org Sat Apr 14 00:20:17 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Sat, 14 Apr 2007 00:20:17 +0200 (CEST) Subject: [Python-checkins] r54814 - python/trunk/PC/getpathp.c Message-ID: <20070413222017.31E551E4004@bag.python.org> Author: kristjan.jonsson Date: Sat Apr 14 00:20:13 2007 New Revision: 54814 Modified: python/trunk/PC/getpathp.c Log: Fix potential crash in path manipulation on windows Modified: python/trunk/PC/getpathp.c ============================================================================== --- python/trunk/PC/getpathp.c (original) +++ python/trunk/PC/getpathp.c Sat Apr 14 00:20:13 2007 @@ -650,7 +650,7 @@ start of the path in question - even if this is one character before the start of the buffer */ - while (*look != DELIM && look >= module_search_path) + while (look >= module_search_path && *look != DELIM) look--; nchars = lookEnd-look; strncpy(lookBuf, look+1, nchars); From python-checkins at python.org Sat Apr 14 00:21:07 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Sat, 14 Apr 2007 00:21:07 +0200 (CEST) Subject: [Python-checkins] r54815 - python/branches/release25-maint/PC/getpathp.c Message-ID: <20070413222107.EC5C11E4003@bag.python.org> Author: kristjan.jonsson Date: Sat Apr 14 00:21:07 2007 New Revision: 54815 Modified: python/branches/release25-maint/PC/getpathp.c Log: Fix potential crash in path manipulation on windows Modified: python/branches/release25-maint/PC/getpathp.c ============================================================================== --- python/branches/release25-maint/PC/getpathp.c (original) +++ python/branches/release25-maint/PC/getpathp.c Sat Apr 14 00:21:07 2007 @@ -650,7 +650,7 @@ start of the path in question - even if this is one character before the start of the buffer */ - while (*look != DELIM && look >= module_search_path) + while (look >= module_search_path && *look != DELIM) look--; nchars = lookEnd-look; strncpy(lookBuf, look+1, nchars); From python-checkins at python.org Sat Apr 14 01:22:07 2007 From: python-checkins at python.org (trent.mick) Date: Sat, 14 Apr 2007 01:22:07 +0200 (CEST) Subject: [Python-checkins] r54816 - python/trunk/PC/VC6/pcbuild.dsw Message-ID: <20070413232207.9FAA61E4003@bag.python.org> Author: trent.mick Date: Sat Apr 14 01:22:05 2007 New Revision: 54816 Modified: python/trunk/PC/VC6/pcbuild.dsw Log: Add the necessary dependency for the Windows VC6 build to ensure 'pythoncore' is built before '_ctypes' is attempted. Will backport to 2.5 once it is unfrozen for 2.5.1. Modified: python/trunk/PC/VC6/pcbuild.dsw ============================================================================== --- python/trunk/PC/VC6/pcbuild.dsw (original) +++ python/trunk/PC/VC6/pcbuild.dsw Sat Apr 14 01:22:05 2007 @@ -26,6 +26,9 @@ Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name pythoncore + End Project Dependency }}} ############################################################################### From buildbot at python.org Sat Apr 14 02:04:00 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Apr 2007 00:04:00 +0000 Subject: [Python-checkins] buildbot warnings in alpha Tru64 5.1 trunk Message-ID: <20070414000400.D5A721E4003@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%2520trunk/builds/1625 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sat Apr 14 02:21:17 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2007 02:21:17 +0200 (CEST) Subject: [Python-checkins] r54817 - sandbox/trunk/pep0/authors.py Message-ID: <20070414002117.ED32E1E4008@bag.python.org> Author: brett.cannon Date: Sat Apr 14 02:21:16 2007 New Revision: 54817 Added: sandbox/trunk/pep0/authors.py (contents, props changed) Log: Create a module to store author/email info along with nicknames. Added: sandbox/trunk/pep0/authors.py ============================================================================== --- (empty file) +++ sandbox/trunk/pep0/authors.py Sat Apr 14 02:21:16 2007 @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +email_addresses = { + 'Aahz' : 'aahz at pobox.com', + 'James C. Ahlstrom' : 'jim at interet.com', + 'Jim Althoff' : 'james_althoff at i2.com', + 'Kevin Altis' : 'altis at semi-retired.com', + 'David Ascher' : 'davida at activestate.com', + 'Peter Astrand' : 'astrand at lysator.liu.se', + 'Carl Banks' : 'pythondev at aerojockey.com', + 'Paul Barrett' : 'barrett at stsci.edu', + 'Facundo Batista' : 'facundo at taniquetil.com.ar', + 'Anthony Baxter' : 'anthony at interlink.com.au', + 'Thomas Bellman' : 'bellman+pep-divmod at lysator.liu.se', + 'Steven Bethard' : 'steven.bethard at gmail.com', + 'Georg Brandl' : 'g.brandl at gmx.net', + 'Brett Cannon' : 'brett at python.org', + 'Josiah Carlson' : 'jcarlson at uci.edu', + 'W Isaac Carroll' : 'icarroll at pobox.com', + 'Nick Coghlan' : 'ncoghlan at gmail.com', + 'Dave Cole' : 'djc at object-craft.com.au', + 'Christopher Craig' : 'python-pep at ccraig.org', + 'Laura Creighton' : 'lac at strakt.com', + 'Walter D?rwald' : '', + 'Fred L. Drake, Jr.' : 'fdrake at acm.org', + 'Michael P. Dubner' : 'dubnerm at mindless.com', + 'Paul F. Dubois' : 'paul at pfdubois.com', + 'Phillip J. Eby' : 'pje at telecommunity.com', + 'Micah Elliott' : 'mde at tracos.org', + 'Jeff Epler' : 'jepler at unpythonic.net', + 'David Eppstein' : 'eppstein at ics.uci.edu', + 'Clark C. Evans' : 'cce at clarkevans.com', + 'Greg Ewing' : 'greg at cosc.canterbury.ac.nz', + 'Martijn Faassen' : 'faassen at infrae.com', + 'Ben Finney' : 'ben+python at benfinney.id.au', + 'Fr?d?ric B. Giacometti' : 'fred at arakne.com', + 'Scott Gilbert' : 'xscottg at yahoo.com', + 'David Goodger' : 'goodger at python.org', + 'Grant Griffin' : 'g2 at iowegian.com', + 'Mark Hammond' : 'mhammond at skippinet.com.au', + 'Peter Harris' : 'scav at blueyonder.co.uk', + 'Thomas Heller' : 'theller at python.net', + 'Magnus Lie Hetland' : 'magnus at hetland.org', + 'Raymond D. Hettinger' : 'python at rcn.com', + 'Neil Hodgson' : 'neilh at scintilla.org', + 'Michael Hudson' : 'mwh at python.net', + 'Jeremy Hylton' : 'jeremy at zope.com', + 'Jack Jansen' : 'jack at cwi.nl', + 'Jim Jewett' : 'jimjjewett at users.sourceforge.net', + 'Richard Jones' : 'richard at mechanicalcat.net', + 'Stepan Koltsov' : 'yozh at mx1.ru', + 'A.M. Kuchling' : 'amk at amk.ca', + 'Marc-Andre Lemburg' : 'mal at lemburg.com', + 'Gregory Lielens' : 'gregory.lielens at fft.be', + 'Bj?rn Lindqvist' : 'bjourne at gmail.com', + 'Martin von L?wis' : 'loewis at informatik.hu-berlin.de', + 'Tony Lownds' : 'tony at pagedna.com', + 'Alex Martelli' : 'aleax at aleax.it', + 'Andrew McClelland' : 'eternalsquire at comcast.net', + 'Gordon McMillan' : 'gmcm at hypernet.com', + 'Andrew McNamara' : 'andrewm at object-craft.com.au', + 'Trent Mick' : 'trentm at activestate.com', + 'Mike Meyer' : 'mwm at mired.org', + 'Skip Montanaro' : 'skip at pobox.com', + 'Paul Moore' : 'gustav at morpheus.demon.co.uk', + 'Ben North' : 'ben at redfrontdoor.org', + 'Neal Norwitz' : 'nnorwitz at gmail.com', + 'Travis Oliphant' : 'oliphant at ee.byu.edu', + 'Jason Orendorff' : 'jason.orendorff at gmail.com', + 'Samuele Pedroni' : 'pedronis at python.org', + 'Michel Pelletier' : 'michel at users.sourceforge.net', + 'Tim Peters' : 'tim at zope.com', + 'Jason Petrone' : 'jp at demonseed.net', + 'Paul Prescod' : 'paul at prescod.net', + 'Terry Reedy' : 'tjreedy at udel.edu', + 'Sean Reifschneider' : 'jafo-pep at tummy.com', + 'Christian R. Reis' : 'kiko at async.com.br', + 'Jonathan Riehl' : 'jriehl at spaceship.com', + 'Andr? Roberge' : 'andre.roberge at gmail.com', + 'Guido van Rossum' : 'guido at python.org', + 'Just van Rossum' : 'just at letterror.com', + 'Vinay Sajip' : 'vinay_sajip at red-dove.com', + 'Neil Schemenauer' : 'nas at arctrix.com', + 'Peter Schneider-Kamp' : 'nowonder at nowonder.de', + 'Jiwon Seo' : 'seojiwon at gmail.com', + 'Kevin D. Smith' : 'Kevin.Smith at theMorgue.org', + 'Greg Stein' : 'gstein at lyra.org', + 'Daniel Stutzbach' : 'daniel.stutzbach at gmail.com', + 'Roman Suzi' : 'rnd at onego.ru', + 'Talin' : 'talin at acm.org', + 'Steven Taschuk' : 'staschuk at telusplanet.net', + 'Oren Tirosh' : 'oren at hishome.net', + 'Mike Verdone' : 'mike.verdone at gmail.com', + 'Gregory R. Warnes' : 'warnes at users.sourceforge.net', + 'Barry Warsaw' : 'barry at python.org', + 'Terence Way' : 'terry at wayforward.net', + 'Cliff Wells' : 'LogiplexSoftware at earthlink.net', + 'Greg Wilson' : 'gvwilson at ddj.com', + 'Collin Winter' : 'collinw at gmail.com', + 'Thomas Wouters' : 'thomas at python.org', + 'Ka-Ping Yee' : 'ping at zesty.ca', + 'Moshe Zadka' : 'moshez at zadka.site.co.il', + 'Huaiyu Zhu' : 'hzhu at users.sourceforge.net', +} + +nicknames = { + 'Guido van Rossum' : 'GvR', + 'Just van Rossum' : 'JvR', +} From python-checkins at python.org Sat Apr 14 02:30:07 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2007 02:30:07 +0200 (CEST) Subject: [Python-checkins] r54818 - peps/trunk/pep-0207.txt Message-ID: <20070414003007.B94441E4003@bag.python.org> Author: brett.cannon Date: Sat Apr 14 02:30:06 2007 New Revision: 54818 Modified: peps/trunk/pep-0207.txt Log: Fix a typo in the PEP title. Modified: peps/trunk/pep-0207.txt ============================================================================== --- peps/trunk/pep-0207.txt (original) +++ peps/trunk/pep-0207.txt Sat Apr 14 02:30:06 2007 @@ -1,5 +1,5 @@ PEP: 207 -Title: Rich Comparisions +Title: Rich Comparisons Version: $Revision$ Last-Modified: $Date$ Author: guido at python.org (Guido van Rossum), DavidA at ActiveState.com (David Ascher) From python-checkins at python.org Sat Apr 14 02:31:27 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2007 02:31:27 +0200 (CEST) Subject: [Python-checkins] r54819 - peps/trunk/pep-3118.txt Message-ID: <20070414003127.37C791E4003@bag.python.org> Author: brett.cannon Date: Sat Apr 14 02:31:26 2007 New Revision: 54819 Modified: peps/trunk/pep-3118.txt Log: Make Author field's name be consistent with other names (it's not plural). Modified: peps/trunk/pep-3118.txt ============================================================================== --- peps/trunk/pep-3118.txt (original) +++ peps/trunk/pep-3118.txt Sat Apr 14 02:31:26 2007 @@ -2,7 +2,7 @@ Title: Revising the buffer protocol Version: $Revision$ Last-Modified: $Date$ -Authors: Travis Oliphant , Carl Banks +Author: Travis Oliphant , Carl Banks Status: Draft Type: Standards Track Content-Type: text/x-rst From python-checkins at python.org Sat Apr 14 02:33:00 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2007 02:33:00 +0200 (CEST) Subject: [Python-checkins] r54820 - sandbox/trunk/pep0/pep0.py sandbox/trunk/pep0/test_pep0.py Message-ID: <20070414003300.1E5011E4003@bag.python.org> Author: brett.cannon Date: Sat Apr 14 02:32:58 2007 New Revision: 54820 Modified: sandbox/trunk/pep0/pep0.py sandbox/trunk/pep0/test_pep0.py Log: Add support for author nicknames. Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Sat Apr 14 02:32:58 2007 @@ -1,5 +1,6 @@ """Auto-generate PEP 0 (PEP index). """ from __future__ import with_statement +import authors import os import re @@ -65,7 +66,7 @@ angled = r'(?P.+?) <.+?>' paren = r'.+? \((?P.+?)\)' simple = r'(?P[^,]+)' - authors = [] + author_list = [] for regex in (angled, paren, simple): # Watch out for commas separating multiple names. regex += '(,\s+)?' @@ -76,14 +77,15 @@ # separated by commas. author = match.group('author') if not author.partition(' ')[1] and author.endswith('.'): - prev_author = authors.pop() + prev_author = author_list.pop() author = ', '.join([prev_author, author]) - authors.append(author) + author_list.append(author) else: - # If authors were found then stop searching. - if authors: + # If authors were found then stop searching as only expect one + # style of author citation. + if author_list: break - return authors + return author_list def handle_csv(data): """Handle the Post-History.""" @@ -94,8 +96,8 @@ 'Post-History': handle_csv, } -def last_name(full_name): - """Find the last name of a full name. +def last_name(full_name, nicknames={}): + """Find the last name (or nickname) of a full name. If no last name (e.g, 'Aahz') then return the full name. If there is a leading, lowercase portion to the last name (e.g., 'van' or 'von') then @@ -103,6 +105,9 @@ comma, then drop the suffix. """ + nickname = nicknames.get(full_name) + if nickname: + return nickname no_suffix = full_name.partition(',')[0] name_parts = no_suffix.split() part_count = len(name_parts) @@ -154,9 +159,11 @@ number = str(pep['PEP']).rjust(4) title = pep['Title'] authors_list = [] - authors = ', '.join(last_name(author) for author in pep['Author']) + author_string = ', '.join(last_name(author, authors.nicknames) + for author in pep['Author']) output.write(" %s%s %s %s %s\n" % - (type_abbr, status_abbr, number, title.ljust(44), authors)) + (type_abbr, status_abbr, number, title.ljust(44), + author_string)) if __name__ == '__main__': Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Sat Apr 14 02:32:58 2007 @@ -157,6 +157,17 @@ got = pep0.last_name(full_name) self.failUnlessEqual(got, expect) + def test_author_nickname(self): + # Make sure nicknames are returned instead of last names when a + # nickname is available. + full_name = 'Guido van Rossum' + nickname = 'GvR' + last_name = 'van Rossum' + got = pep0.last_name(full_name, {full_name:nickname}) + self.failUnlessEqual(got, nickname) + got = pep0.last_name(full_name, {'asdf':nickname}) + self.failUnlessEqual(got, last_name) + def test_main(): test_support.run_unittest( From python-checkins at python.org Sat Apr 14 02:34:43 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2007 02:34:43 +0200 (CEST) Subject: [Python-checkins] r54821 - sandbox/trunk/pep0/TODO Message-ID: <20070414003443.63C561E4003@bag.python.org> Author: brett.cannon Date: Sat Apr 14 02:34:42 2007 New Revision: 54821 Modified: sandbox/trunk/pep0/TODO Log: Update TODO that authors index has been implemented. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Sat Apr 14 02:34:42 2007 @@ -1,26 +1,9 @@ -Current discrepencies/bugs --------------------------- - -* Be able to import authors.py . - - Probably as simple as declaring encoding. - - Otherwise prepend 'u' to every string. - - - Functionality to add -------------------- * Read PEPs as UTF-8. * Output static text for PEP 0. - + Store Owners list in a data structure. - - Support nicknames for PEP listing (e.g., "Guido van Rossum" -> - "GvR"). - - Care about making sure that email addresses are up-to-date between - PEPs and PEP 0? - - Worth keeping emails in both PEP 0 and individual PEPs, or just make - PEP 0 master and leave out of PEPs so that single place can be - maintained and considered up-to-date? + Store Key in data structure for easy mapping? - Would allow for easy validation that metadata is correct in PEPs. @@ -39,8 +22,8 @@ - reST. -Inconsistencies ----------------- +Inconsistencies/Things To Improve +--------------------------------- * Within PEPs: + Author field From python-checkins at python.org Sat Apr 14 02:49:05 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2007 02:49:05 +0200 (CEST) Subject: [Python-checkins] r54822 - sandbox/trunk/pep0/pep0.py Message-ID: <20070414004905.6B00D1E4003@bag.python.org> Author: brett.cannon Date: Sat Apr 14 02:48:59 2007 New Revision: 54822 Modified: sandbox/trunk/pep0/pep0.py Log: Output key information. Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Sat Apr 14 02:48:59 2007 @@ -4,6 +4,9 @@ import os import re +type_values = ("Standards Track", "Informational", "Process") +status_values = ("Accepted", "Rejected", "Withdrawn", "Deferred", "Final") + def consume_headers(directory='.'): """Pull out metadata for every PEP in the specified directory and return them in a list sorted by PEP name.""" @@ -178,7 +181,28 @@ else: peps = [consume_pep(path)] + + #XXX meta, info, accepted, open_, done, empty, dead = sort_peps(peps) + for pep in peps: write_pep(pep, stdout) - #meta, info, accepted, open_, done, empty, dead = sort_peps(peps) + print + print + print "Key" + print + for type_ in type_values: + print " %s - %s PEP" % (type_[0], type_) + print + for status in status_values: + print " %s - %s proposal" % (status[0], status) + + print + print + print "Owners" + print + # XXX list by last name, sort (take into account van/von and Jr.), list + # nickname, and + # output with email. Need to know longest one for both fields to make sure + # list header is long enough and proper padding between name and email is + # done. From python-checkins at python.org Sat Apr 14 02:58:04 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2007 02:58:04 +0200 (CEST) Subject: [Python-checkins] r54823 - sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py Message-ID: <20070414005804.0C45F1E4003@bag.python.org> Author: brett.cannon Date: Sat Apr 14 02:58:00 2007 New Revision: 54823 Modified: sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py Log: Clarify what is left to do. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Sat Apr 14 02:58:00 2007 @@ -4,12 +4,21 @@ * Read PEPs as UTF-8. * Output static text for PEP 0. - + Store Key in data structure for easy mapping? - - Would allow for easy validation that metadata is correct in PEPs. - -* Output PEP 0 with numerical PEP index. + + Header. + + Footer. + + References. + + Column titles for numerical index. + + Author/email list. + - names + - emails + - Column headers. + * Underline to length of author name or just column header like in + rest of doc? * Output PEP 0 with special sections. + + Sort PEPs. + + Column headers. + + Section info. * Make sure that it is easy to identify which PEP triggered an error. + Has all expected fields. Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Sat Apr 14 02:58:00 2007 @@ -201,8 +201,9 @@ print print "Owners" print - # XXX list by last name, sort (take into account van/von and Jr.), list - # nickname, and - # output with email. Need to know longest one for both fields to make sure - # list header is long enough and proper padding between name and email is - # done. + # XXX + # * get "last, first I." of each name. + # * add nickname. + # * find longest name. + # * column headers. + # * name/email with a two-space separation between longest name and email. From buildbot at python.org Sat Apr 14 02:58:25 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Apr 2007 00:58:25 +0000 Subject: [Python-checkins] buildbot warnings in alpha Tru64 5.1 2.5 Message-ID: <20070414005826.36B021E4003@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%25202.5/builds/244 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_socket sincerely, -The Buildbot From python-checkins at python.org Sat Apr 14 03:03:33 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2007 03:03:33 +0200 (CEST) Subject: [Python-checkins] r54824 - sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py Message-ID: <20070414010333.EA7821E4003@bag.python.org> Author: brett.cannon Date: Sat Apr 14 03:03:29 2007 New Revision: 54824 Modified: sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py Log: Add in static text to file (but not to output). Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Sat Apr 14 03:03:29 2007 @@ -6,6 +6,7 @@ * Output static text for PEP 0. + Header. + Footer. + + Introduction. + References. + Column titles for numerical index. + Author/email list. Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Sat Apr 14 03:03:29 2007 @@ -4,6 +4,50 @@ import os import re +# Don't start on a new line to make easier to read as that would cause output to +# start on a blank line. +header = """PEP: 0 +Title: Index of Python Enhancement Proposals (PEPs) +Version: $Revision$ +Last-Modified: $Date$ +Author: David Goodger , + Barry A. Warsaw +Status: Active +Type: Informational +Created: 13-Jul-2000 +""" + +intro = """ + The PEP contains the index of all Python Enhancement Proposals, + known as PEPs. PEP numbers are assigned by the PEP Editor, and + once assigned are never changed. The SVN history[1] of the PEP + texts represent their historical record. + + The BDFL maintains his own Pronouncements page[2] at + http://www.python.org/doc/essays/pepparade.html which contains his + musings on the various outstanding PEPs. +""" + +references = """ + [1] View PEP history online + http://svn.python.org/projects/peps/trunk/ + + [2] The Benevolent Dictator For Life's Parade of PEPs + http://www.python.org/doc/essays/pepparade.html +""" + +footer = """ + +Local Variables: +mode: indented-text +indent-tabs-mode: nil +sentence-end-double-space: t +fill-column: 70 +coding: utf-8 +End: +""" + + type_values = ("Standards Track", "Informational", "Process") status_values = ("Accepted", "Rejected", "Withdrawn", "Deferred", "Final") From python-checkins at python.org Sat Apr 14 07:25:58 2007 From: python-checkins at python.org (neal.norwitz) Date: Sat, 14 Apr 2007 07:25:58 +0200 (CEST) Subject: [Python-checkins] r54825 - in python/trunk: Lib/test/test_descr.py Misc/NEWS Objects/typeobject.c Message-ID: <20070414052558.078C41E4003@bag.python.org> Author: neal.norwitz Date: Sat Apr 14 07:25:50 2007 New Revision: 54825 Modified: python/trunk/Lib/test/test_descr.py python/trunk/Misc/NEWS python/trunk/Objects/typeobject.c Log: When __slots__ are set to a unicode string, make it work the same as setting a plain string, ie don't expand to single letter identifiers. Modified: python/trunk/Lib/test/test_descr.py ============================================================================== --- python/trunk/Lib/test/test_descr.py (original) +++ python/trunk/Lib/test/test_descr.py Sat Apr 14 07:25:50 2007 @@ -1225,13 +1225,29 @@ raise TestFailed, "[''] slots not caught" class C(object): __slots__ = ["a", "a_b", "_a", "A0123456789Z"] + # XXX(nnorwitz): was there supposed to be something tested + # from the class above? + + # Test a single string is not expanded as a sequence. + class C(object): + __slots__ = "abc" + c = C() + c.abc = 5 + vereq(c.abc, 5) # Test unicode slot names try: - unichr + unicode except NameError: pass else: + # Test a single unicode string is not expanded as a sequence. + class C(object): + __slots__ = unicode("abc") + c = C() + c.abc = 5 + vereq(c.abc, 5) + # _unicode_to_string used to modify slots in certain circumstances slots = (unicode("foo"), unicode("bar")) class C(object): Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Apr 14 07:25:50 2007 @@ -12,6 +12,9 @@ Core and builtins ----------------- +- When __slots__ are set to a unicode string, make it work the same as + setting a plain string, ie don't expand to single letter identifiers. + - Request #1191699: Slices can now be pickled. - Request #1193128: str.translate() now allows a None argument for Modified: python/trunk/Objects/typeobject.c ============================================================================== --- python/trunk/Objects/typeobject.c (original) +++ python/trunk/Objects/typeobject.c Sat Apr 14 07:25:50 2007 @@ -1816,7 +1816,7 @@ /* Have slots */ /* Make it into a tuple */ - if (PyString_Check(slots)) + if (PyString_Check(slots) || PyUnicode_Check(slots)) slots = PyTuple_Pack(1, slots); else slots = PySequence_Tuple(slots); From buildbot at python.org Sat Apr 14 07:41:58 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Apr 2007 05:41:58 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP trunk Message-ID: <20070414054158.B24441E4003@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/378 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: neal.norwitz Build had warnings: warnings failed slave lost sincerely, -The Buildbot From stackless-checkins-bounces at stackless.com Sat Apr 14 15:06:00 2007 From: stackless-checkins-bounces at stackless.com (stackless-checkins-bounces at stackless.com) Date: Sat, 14 Apr 2007 15:06:00 +0200 Subject: [Python-checkins] Your message to Stackless-checkins awaits moderator approval Message-ID: Your mail to 'Stackless-checkins' with the subject r54826 - in stackless/branches/release25-maint: Demo/parser/unparse.py Doc/README Doc/api/abstract.tex Doc/api/concrete.tex Doc/api/exceptions.tex Doc/api/memory.tex Doc/api/newtypes.tex Doc/api/utilities.tex Doc/commontex/boilerplate.tex Doc/commontex/license.tex Doc/dist/dist.tex Doc/ext/newtypes.tex Doc/ext/shoddy.c Doc/inst/inst.tex Doc/lib/emailgenerator.tex Doc/lib/libasyncore.tex Doc/lib/libbase64.tex Doc/lib/libbsddb.tex Doc/lib/libbz2.tex Doc/lib/libcollections.tex Doc/lib/libcommands.tex Doc/lib/libcsv.tex Doc/lib/libctypes.tex Doc/lib/libdbhash.tex Doc/lib/libfnmatch.tex Doc/lib/libfuncs.tex Doc/lib/libfunctools.tex Doc/lib/libgetopt.tex Doc/lib/libgettext.tex Doc/lib/libheapq.tex Doc/lib/libimageop.tex Doc/lib/libitertools.tex Doc/lib/liblocale.tex Doc/lib/liblogging.tex Doc/lib/libmailbox.tex Doc/lib/libmmap.tex Doc/lib/libmsilib.tex Doc/lib/libos.tex Doc/lib/libpickle.tex Doc/lib/libpopen2.tex Doc/lib/libprofile.tex Doc/lib/librandom.tex Doc/lib/libshu! til.tex Doc/lib/libsimplexmlrpc.tex Doc/lib/libsmtplib.tex Doc/lib/libsocket.tex Doc/lib/libsqlite3.tex Doc/lib/libstdtypes.tex Doc/lib/libstring.tex Doc/lib/libstruct.tex Doc/lib/libsubprocess.tex Doc/lib/libtarfile.tex Doc/lib/libtempfile.tex Doc/lib/libthreading.tex Doc/lib/libtimeit.tex Doc/lib/libunittest.tex Doc/lib/liburlparse.tex Doc/lib/libwsgiref.tex Doc/lib/tkinter.tex Doc/mac/toolbox.tex Doc/ref/ref1.tex Doc/ref/ref3.tex Doc/ref/ref5.tex Doc/ref/ref6.tex Doc/ref/ref7.tex Doc/tools/py2texi.el Doc/tut/tut.tex Doc/whatsnew/whatsnew25.tex Include/Python-ast.h Include/abstract.h Include/dictobject.h Include/patchlevel.h Include/pystate.h Include/setobject.h LICENSE Lib/CGIHTTPServer.py Lib/Queue.py Lib/SimpleHTTPServer.py Lib/SocketServer.py Lib/StringIO.py Lib/_strptime.py Lib/bisect.py Lib/bsddb/dbobj.py Lib/bsddb/test/test_1413192.py Lib/bsddb/test/test_dbobj.py Lib/codecs.py Lib/compiler/pycodegen.py Lib/compiler/transformer.py Lib/ctypes Lib/ctypes/__init__.py L! ib/ctypes/test/test_callbacks.py Lib/ctypes/test/test_functions.py Lib/ctypes/test/test_loading.py Lib/ctypes/test/test_memfunctions.py Lib/ctypes/test/test_structures.py Lib/ctypes/util.py Lib/decimal.py Lib/difflib.py Lib/distutils/__init__.py Lib/distutils/command/bdist_rpm.py Lib/distutils/command/build_ext.py Lib/distut Is being held until the list moderator can review it for approval. The reason it is being held: Message body is too big: 909930 bytes with a limit of 500 KB Either the message will get posted to the list, or you will receive notification of the moderator's decision. If you would like to cancel this posting, please visit the following URL: http://www.stackless.com/mailman/confirm/stackless-checkins/793022e0e2f4ffef76427874acc8923d75b2d392 From python-checkins at python.org Sun Apr 15 03:35:34 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2007 03:35:34 +0200 (CEST) Subject: [Python-checkins] r54828 - sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py Message-ID: <20070415013534.60D551E4008@bag.python.org> Author: brett.cannon Date: Sun Apr 15 03:35:29 2007 New Revision: 54828 Modified: sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py Log: Flesh out output of static text. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Sun Apr 15 03:35:29 2007 @@ -4,11 +4,6 @@ * Read PEPs as UTF-8. * Output static text for PEP 0. - + Header. - + Footer. - + Introduction. - + References. - + Column titles for numerical index. + Author/email list. - names - emails @@ -16,9 +11,8 @@ * Underline to length of author name or just column header like in rest of doc? -* Output PEP 0 with special sections. - + Sort PEPs. - + Column headers. +* Index by Category. + + Sort PEPs and output + Section info. * Make sure that it is easy to identify which PEP triggered an error. Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Sun Apr 15 03:35:29 2007 @@ -36,16 +36,14 @@ http://www.python.org/doc/essays/pepparade.html """ -footer = """ - +footer = """ Local Variables: mode: indented-text indent-tabs-mode: nil sentence-end-double-space: t fill-column: 70 coding: utf-8 -End: -""" +End:""" type_values = ("Standards Track", "Informational", "Process") @@ -212,6 +210,13 @@ (type_abbr, status_abbr, number, title.ljust(44), author_string)) +def write_column_headers(output): + """Output the column headers for the PEP indices.""" + output.write('%s %s %s\n' % ("num".rjust(8), "title".ljust(44), "owner")) + output.write('%s %s %s\n' % ((len("num")*'-').rjust(8), + (len("title")*'-').ljust(44), len("owner")*'-')) + + if __name__ == '__main__': from sys import argv, stdout @@ -225,12 +230,27 @@ else: peps = [consume_pep(path)] - + print header + print + print "Introduction" + print intro + print + print "Index by Category" + print + write_column_headers(stdout) #XXX meta, info, accepted, open_, done, empty, dead = sort_peps(peps) - + print ' XXX' + print + print + print "Numerical Index" + print + write_column_headers(stdout) + prev_pep = 0 for pep in peps: + if pep['PEP'] - prev_pep > 1: + print write_pep(pep, stdout) - + prev_pep = pep['PEP'] print print print "Key" @@ -251,3 +271,10 @@ # * find longest name. # * column headers. # * name/email with a two-space separation between longest name and email. + print ' XXX' + print + print + print "References" + print + print references + print footer From python-checkins at python.org Sun Apr 15 04:08:40 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2007 04:08:40 +0200 (CEST) Subject: [Python-checkins] r54829 - peps/trunk/pep-0314.txt Message-ID: <20070415020840.4C3191E4003@bag.python.org> Author: brett.cannon Date: Sun Apr 15 04:08:39 2007 New Revision: 54829 Modified: peps/trunk/pep-0314.txt Log: Make author listing consistent. Modified: peps/trunk/pep-0314.txt ============================================================================== --- peps/trunk/pep-0314.txt (original) +++ peps/trunk/pep-0314.txt Sun Apr 15 04:08:39 2007 @@ -2,7 +2,7 @@ Title: Metadata for Python Software Packages v1.1 Version: $Revision$ Last-Modified: $Date$ -Author: A.M. Kuchling , Richard Jones +Author: A.M. Kuchling, Richard Jones Status: Final Type: Standards Track Content-type: text/plain From python-checkins at python.org Sun Apr 15 04:10:31 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2007 04:10:31 +0200 (CEST) Subject: [Python-checkins] r54830 - peps/trunk/pep-0160.txt peps/trunk/pep-0205.txt peps/trunk/pep-0207.txt peps/trunk/pep-0214.txt peps/trunk/pep-0229.txt peps/trunk/pep-0231.txt peps/trunk/pep-3101.txt peps/trunk/pep-3102.txt peps/trunk/pep-3105.txt peps/trunk/pep-3106.txt peps/trunk/pep-3115.txt Message-ID: <20070415021031.B92121E4003@bag.python.org> Author: brett.cannon Date: Sun Apr 15 04:10:27 2007 New Revision: 54830 Modified: peps/trunk/pep-0160.txt peps/trunk/pep-0205.txt peps/trunk/pep-0207.txt peps/trunk/pep-0214.txt peps/trunk/pep-0229.txt peps/trunk/pep-0231.txt peps/trunk/pep-3101.txt peps/trunk/pep-3102.txt peps/trunk/pep-3105.txt peps/trunk/pep-3106.txt peps/trunk/pep-3115.txt Log: Make Type field values consistent across all PEPs. Modified: peps/trunk/pep-0160.txt ============================================================================== --- peps/trunk/pep-0160.txt (original) +++ peps/trunk/pep-0160.txt Sun Apr 15 04:10:27 2007 @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Fred L. Drake, Jr. -Status: Finished +Status: Final Type: Informational Created: 25-Jul-2000 Python-Version: 1.6 Modified: peps/trunk/pep-0205.txt ============================================================================== --- peps/trunk/pep-0205.txt (original) +++ peps/trunk/pep-0205.txt Sun Apr 15 04:10:27 2007 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Fred L. Drake, Jr. Python-Version: 2.1 -Status: Incomplete +Status: Final Type: Standards Track Post-History: 11-Jan-2001 Modified: peps/trunk/pep-0207.txt ============================================================================== --- peps/trunk/pep-0207.txt (original) +++ peps/trunk/pep-0207.txt Sun Apr 15 04:10:27 2007 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: guido at python.org (Guido van Rossum), DavidA at ActiveState.com (David Ascher) Python-Version: 2.1 -Type: Standards +Type: Standards Track Status: Final Modified: peps/trunk/pep-0214.txt ============================================================================== --- peps/trunk/pep-0214.txt (original) +++ peps/trunk/pep-0214.txt Sun Apr 15 04:10:27 2007 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: barry at python.org (Barry A. Warsaw) Python-Version: 2.0 -Type: Standards +Type: Standards Track Status: Final Created: 24-Jul-2000 Post-History: 16-Aug-2000 Modified: peps/trunk/pep-0229.txt ============================================================================== --- peps/trunk/pep-0229.txt (original) +++ peps/trunk/pep-0229.txt Sun Apr 15 04:10:27 2007 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: A.M. Kuchling Status: Final -Type: Standards +Type: Standards Track Created: 16-Nov-2000 Post-History: Modified: peps/trunk/pep-0231.txt ============================================================================== --- peps/trunk/pep-0231.txt (original) +++ peps/trunk/pep-0231.txt Sun Apr 15 04:10:27 2007 @@ -5,7 +5,7 @@ Author: barry at python.org (Barry A. Warsaw) Python-Version: 2.1 Status: Rejected -Type: Standards +Type: Standards Track Created: 30-Nov-2000 Post-History: Modified: peps/trunk/pep-3101.txt ============================================================================== --- peps/trunk/pep-3101.txt (original) +++ peps/trunk/pep-3101.txt Sun Apr 15 04:10:27 2007 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Talin Status: Draft -Type: Standards +Type: Standards Track Content-Type: text/plain Created: 16-Apr-2006 Python-Version: 3.0 Modified: peps/trunk/pep-3102.txt ============================================================================== --- peps/trunk/pep-3102.txt (original) +++ peps/trunk/pep-3102.txt Sun Apr 15 04:10:27 2007 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Talin Status: Accepted -Type: Standards +Type: Standards Track Content-Type: text/plain Created: 22-Apr-2006 Python-Version: 3.0 Modified: peps/trunk/pep-3105.txt ============================================================================== --- peps/trunk/pep-3105.txt (original) +++ peps/trunk/pep-3105.txt Sun Apr 15 04:10:27 2007 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Georg Brandl Status: Final -Type: Standards +Type: Standards Track Content-Type: text/x-rst Created: 19-Nov-2006 Python-Version: 3.0 Modified: peps/trunk/pep-3106.txt ============================================================================== --- peps/trunk/pep-3106.txt (original) +++ peps/trunk/pep-3106.txt Sun Apr 15 04:10:27 2007 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Guido van Rossum Status: Accepted -Type: Standards +Type: Standards Track Content-Type: text/x-rst Created: 19-Dec-2006 Post-History: Modified: peps/trunk/pep-3115.txt ============================================================================== --- peps/trunk/pep-3115.txt (original) +++ peps/trunk/pep-3115.txt Sun Apr 15 04:10:27 2007 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Talin Status: Accepted -Type: Standards +Type: Standards Track Content-Type: text/plain Created: 07-Mar-2007 Python-Version: 3.0 From python-checkins at python.org Sun Apr 15 04:15:05 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2007 04:15:05 +0200 (CEST) Subject: [Python-checkins] r54831 - sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py Message-ID: <20070415021505.C322B1E4003@bag.python.org> Author: brett.cannon Date: Sun Apr 15 04:15:01 2007 New Revision: 54831 Modified: sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0.py Log: Get the index to output by category. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Sun Apr 15 04:15:01 2007 @@ -3,23 +3,15 @@ * Read PEPs as UTF-8. -* Output static text for PEP 0. - + Author/email list. - - names - - emails - - Column headers. - * Underline to length of author name or just column header like in - rest of doc? - -* Index by Category. - + Sort PEPs and output - + Section info. +* Author/email list. + + names + + emails + + Column headers. + - Underline to length of author name or just column header like in + rest of doc? * Make sure that it is easy to identify which PEP triggered an error. - + Has all expected fields. + Values in fields correct. - - Type - - Status - All authors declared in authors.py. + Formatting correct. - Plaintext. @@ -41,8 +33,6 @@ - Meta-PEPs are not delineated as such. + Status field. - - Not all PEPs use consistent names (e.g., some just say "Standard" instead - of "Standard Track"). - Empty PEPs are not specified as such. * In the index: @@ -61,5 +51,7 @@ - Just deal with some being longer than expected? * Type/Status field. - + Informational PEPs inconsistenty leave out Status. + + Active and Draft status is not listed in index. + - Conflicts with Accepted and Deferred initials, respectively. + - Worth using other letters? Modified: sandbox/trunk/pep0/pep0.py ============================================================================== --- sandbox/trunk/pep0/pep0.py (original) +++ sandbox/trunk/pep0/pep0.py Sun Apr 15 04:15:01 2007 @@ -47,7 +47,9 @@ type_values = ("Standards Track", "Informational", "Process") -status_values = ("Accepted", "Rejected", "Withdrawn", "Deferred", "Final") +# Active and Draft are not listed in the index. +status_values = ("Accepted", "Rejected", "Withdrawn", "Deferred", "Final", + "Active", "Draft") def consume_headers(directory='.'): """Pull out metadata for every PEP in the specified directory and return @@ -74,6 +76,19 @@ except Exception: print "In", pep_file raise + if not 'PEP' in pep_info: + raise ValueError("PEP at file %s lacks a PEP number" % path) + if not 'Author' in pep_info: + raise ValueError("PEP %s is missing the Author field" % + pep_info['PEP']) + if len(pep_info['Author']) < 1: + raise ValueError("PEP %s is lacking authors" % pep_info['PEP']) + if pep_info['Type'] not in type_values: + raise ValueError("%s is an invalid Type value for PEP %s" % + (pep_info['Type'], pep_info['PEP'])) + if pep_info['Status'] not in status_values: + raise ValueError("%s is an invalid Status value for PEP %s" % + (pep_info['Status'], pep_info['PEP'])) return pep_info def parse_metadata(pep_info, line, previous_type=None): @@ -176,28 +191,28 @@ empty = [] dead = [] for pep in peps: - # XXX not all meta PEPs are process PEPs. - if pep['Type'] == 'Process': + # Order of 'if' statement important. Key Status values take precedence + # over Type value, and vice-versa. + if pep['Status'] == 'Draft': + open_.append(pep) + elif pep['Status'] in ('Rejected', 'Withdrawn', 'Deferred', + 'Incomplete'): + dead.append(pep) + elif pep['Type'] == 'Process': meta.append(pep) elif pep['Type'] == 'Informational': info.append(pep) elif pep['Status'] == 'Accepted': accepted.append(pep) - elif pep['Status'] == 'Draft': - open_.append(pep) elif pep['Status'] == 'Final': finished.append(pep) - # XXX empty - elif pep['Status'] in ('Rejected', 'Withdrawn', 'Deferred', - 'Incomplete'): - dead.append(pep) - return meta, info, accepted, open_, finished, empty, dead + return meta, info, accepted, open_, finished, empty, dead def write_pep(pep, output): """Write PEP info to 'output'.""" type_abbr = pep['Type'][0].upper() status = pep['Status'] - if status == 'Draft': + if status in ('Draft', 'Active'): status_abbr = ' ' else: status_abbr = status[0].upper() @@ -238,11 +253,45 @@ print "Index by Category" print write_column_headers(stdout) - #XXX meta, info, accepted, open_, done, empty, dead = sort_peps(peps) - print ' XXX' + meta, info, accepted, open_, done, empty, dead = sort_peps(peps) + print + print " Meta-PEPs (PEPs about PEPs or Processs)" + print + for pep in meta: + write_pep(pep, stdout) + print + print " Other Informational PEPs" + print + for pep in info: + write_pep(pep, stdout) + print + print " Accepted PEPs (accepted; may not be implemented yet)" + print + for pep in accepted: + write_pep(pep, stdout) + print + print " Open PEPs (under consideration)" + print + for pep in open_: + write_pep(pep, stdout) + print + print " Finished PEPs (done, implemented in code repository)" + print + for pep in done: + write_pep(pep, stdout) + print + print " Empty PEPs (or containing only abstract)" + print + for pep in empty: + write_pep(pep, stdout) + print + print " Deferred, Abandoned, Withdrawn, and Rejected PEPs" + print + for pep in dead: + write_pep(pep, stdout) print print - print "Numerical Index" + print " Numerical Index" print write_column_headers(stdout) prev_pep = 0 From python-checkins at python.org Sun Apr 15 05:21:50 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2007 05:21:50 +0200 (CEST) Subject: [Python-checkins] r54832 - in sandbox/trunk/pep0: authors.py pep0 pep0.py pep0/__init__.py pep0/authors.py pep0/output.py pep0/parse.py pep0/pep.py pep0/statictext.py test_pep0.py Message-ID: <20070415032150.E65671E4005@bag.python.org> Author: brett.cannon Date: Sun Apr 15 05:21:46 2007 New Revision: 54832 Added: sandbox/trunk/pep0/pep0/ sandbox/trunk/pep0/pep0/__init__.py (contents, props changed) sandbox/trunk/pep0/pep0/authors.py (contents, props changed) sandbox/trunk/pep0/pep0/output.py (contents, props changed) sandbox/trunk/pep0/pep0/parse.py (contents, props changed) sandbox/trunk/pep0/pep0/pep.py (contents, props changed) sandbox/trunk/pep0/pep0/statictext.py (contents, props changed) Removed: sandbox/trunk/pep0/authors.py sandbox/trunk/pep0/pep0.py Modified: sandbox/trunk/pep0/test_pep0.py Log: Start to refactor code into a package to make discrete steps in creating index more obvious and easier to handle. Still need to break out metadata parsing and validation into separate steps. Also need to rework output. See docstring in pep0.__init__ for discrete steps that are planned. Tests are now totally broken and need to be regrouped based on new package structure. But code can still be run (using ``-m pep0 ``). Deleted: /sandbox/trunk/pep0/authors.py ============================================================================== --- /sandbox/trunk/pep0/authors.py Sun Apr 15 05:21:46 2007 +++ (empty file) @@ -1,108 +0,0 @@ -# -*- coding: utf-8 -*- -email_addresses = { - 'Aahz' : 'aahz at pobox.com', - 'James C. Ahlstrom' : 'jim at interet.com', - 'Jim Althoff' : 'james_althoff at i2.com', - 'Kevin Altis' : 'altis at semi-retired.com', - 'David Ascher' : 'davida at activestate.com', - 'Peter Astrand' : 'astrand at lysator.liu.se', - 'Carl Banks' : 'pythondev at aerojockey.com', - 'Paul Barrett' : 'barrett at stsci.edu', - 'Facundo Batista' : 'facundo at taniquetil.com.ar', - 'Anthony Baxter' : 'anthony at interlink.com.au', - 'Thomas Bellman' : 'bellman+pep-divmod at lysator.liu.se', - 'Steven Bethard' : 'steven.bethard at gmail.com', - 'Georg Brandl' : 'g.brandl at gmx.net', - 'Brett Cannon' : 'brett at python.org', - 'Josiah Carlson' : 'jcarlson at uci.edu', - 'W Isaac Carroll' : 'icarroll at pobox.com', - 'Nick Coghlan' : 'ncoghlan at gmail.com', - 'Dave Cole' : 'djc at object-craft.com.au', - 'Christopher Craig' : 'python-pep at ccraig.org', - 'Laura Creighton' : 'lac at strakt.com', - 'Walter D?rwald' : '', - 'Fred L. Drake, Jr.' : 'fdrake at acm.org', - 'Michael P. Dubner' : 'dubnerm at mindless.com', - 'Paul F. Dubois' : 'paul at pfdubois.com', - 'Phillip J. Eby' : 'pje at telecommunity.com', - 'Micah Elliott' : 'mde at tracos.org', - 'Jeff Epler' : 'jepler at unpythonic.net', - 'David Eppstein' : 'eppstein at ics.uci.edu', - 'Clark C. Evans' : 'cce at clarkevans.com', - 'Greg Ewing' : 'greg at cosc.canterbury.ac.nz', - 'Martijn Faassen' : 'faassen at infrae.com', - 'Ben Finney' : 'ben+python at benfinney.id.au', - 'Fr?d?ric B. Giacometti' : 'fred at arakne.com', - 'Scott Gilbert' : 'xscottg at yahoo.com', - 'David Goodger' : 'goodger at python.org', - 'Grant Griffin' : 'g2 at iowegian.com', - 'Mark Hammond' : 'mhammond at skippinet.com.au', - 'Peter Harris' : 'scav at blueyonder.co.uk', - 'Thomas Heller' : 'theller at python.net', - 'Magnus Lie Hetland' : 'magnus at hetland.org', - 'Raymond D. Hettinger' : 'python at rcn.com', - 'Neil Hodgson' : 'neilh at scintilla.org', - 'Michael Hudson' : 'mwh at python.net', - 'Jeremy Hylton' : 'jeremy at zope.com', - 'Jack Jansen' : 'jack at cwi.nl', - 'Jim Jewett' : 'jimjjewett at users.sourceforge.net', - 'Richard Jones' : 'richard at mechanicalcat.net', - 'Stepan Koltsov' : 'yozh at mx1.ru', - 'A.M. Kuchling' : 'amk at amk.ca', - 'Marc-Andre Lemburg' : 'mal at lemburg.com', - 'Gregory Lielens' : 'gregory.lielens at fft.be', - 'Bj?rn Lindqvist' : 'bjourne at gmail.com', - 'Martin von L?wis' : 'loewis at informatik.hu-berlin.de', - 'Tony Lownds' : 'tony at pagedna.com', - 'Alex Martelli' : 'aleax at aleax.it', - 'Andrew McClelland' : 'eternalsquire at comcast.net', - 'Gordon McMillan' : 'gmcm at hypernet.com', - 'Andrew McNamara' : 'andrewm at object-craft.com.au', - 'Trent Mick' : 'trentm at activestate.com', - 'Mike Meyer' : 'mwm at mired.org', - 'Skip Montanaro' : 'skip at pobox.com', - 'Paul Moore' : 'gustav at morpheus.demon.co.uk', - 'Ben North' : 'ben at redfrontdoor.org', - 'Neal Norwitz' : 'nnorwitz at gmail.com', - 'Travis Oliphant' : 'oliphant at ee.byu.edu', - 'Jason Orendorff' : 'jason.orendorff at gmail.com', - 'Samuele Pedroni' : 'pedronis at python.org', - 'Michel Pelletier' : 'michel at users.sourceforge.net', - 'Tim Peters' : 'tim at zope.com', - 'Jason Petrone' : 'jp at demonseed.net', - 'Paul Prescod' : 'paul at prescod.net', - 'Terry Reedy' : 'tjreedy at udel.edu', - 'Sean Reifschneider' : 'jafo-pep at tummy.com', - 'Christian R. Reis' : 'kiko at async.com.br', - 'Jonathan Riehl' : 'jriehl at spaceship.com', - 'Andr? Roberge' : 'andre.roberge at gmail.com', - 'Guido van Rossum' : 'guido at python.org', - 'Just van Rossum' : 'just at letterror.com', - 'Vinay Sajip' : 'vinay_sajip at red-dove.com', - 'Neil Schemenauer' : 'nas at arctrix.com', - 'Peter Schneider-Kamp' : 'nowonder at nowonder.de', - 'Jiwon Seo' : 'seojiwon at gmail.com', - 'Kevin D. Smith' : 'Kevin.Smith at theMorgue.org', - 'Greg Stein' : 'gstein at lyra.org', - 'Daniel Stutzbach' : 'daniel.stutzbach at gmail.com', - 'Roman Suzi' : 'rnd at onego.ru', - 'Talin' : 'talin at acm.org', - 'Steven Taschuk' : 'staschuk at telusplanet.net', - 'Oren Tirosh' : 'oren at hishome.net', - 'Mike Verdone' : 'mike.verdone at gmail.com', - 'Gregory R. Warnes' : 'warnes at users.sourceforge.net', - 'Barry Warsaw' : 'barry at python.org', - 'Terence Way' : 'terry at wayforward.net', - 'Cliff Wells' : 'LogiplexSoftware at earthlink.net', - 'Greg Wilson' : 'gvwilson at ddj.com', - 'Collin Winter' : 'collinw at gmail.com', - 'Thomas Wouters' : 'thomas at python.org', - 'Ka-Ping Yee' : 'ping at zesty.ca', - 'Moshe Zadka' : 'moshez at zadka.site.co.il', - 'Huaiyu Zhu' : 'hzhu at users.sourceforge.net', -} - -nicknames = { - 'Guido van Rossum' : 'GvR', - 'Just van Rossum' : 'JvR', -} Deleted: /sandbox/trunk/pep0/pep0.py ============================================================================== --- /sandbox/trunk/pep0/pep0.py Sun Apr 15 05:21:46 2007 +++ (empty file) @@ -1,329 +0,0 @@ -"""Auto-generate PEP 0 (PEP index). """ -from __future__ import with_statement -import authors -import os -import re - -# Don't start on a new line to make easier to read as that would cause output to -# start on a blank line. -header = """PEP: 0 -Title: Index of Python Enhancement Proposals (PEPs) -Version: $Revision$ -Last-Modified: $Date$ -Author: David Goodger , - Barry A. Warsaw -Status: Active -Type: Informational -Created: 13-Jul-2000 -""" - -intro = """ - The PEP contains the index of all Python Enhancement Proposals, - known as PEPs. PEP numbers are assigned by the PEP Editor, and - once assigned are never changed. The SVN history[1] of the PEP - texts represent their historical record. - - The BDFL maintains his own Pronouncements page[2] at - http://www.python.org/doc/essays/pepparade.html which contains his - musings on the various outstanding PEPs. -""" - -references = """ - [1] View PEP history online - http://svn.python.org/projects/peps/trunk/ - - [2] The Benevolent Dictator For Life's Parade of PEPs - http://www.python.org/doc/essays/pepparade.html -""" - -footer = """ -Local Variables: -mode: indented-text -indent-tabs-mode: nil -sentence-end-double-space: t -fill-column: 70 -coding: utf-8 -End:""" - - -type_values = ("Standards Track", "Informational", "Process") -# Active and Draft are not listed in the index. -status_values = ("Accepted", "Rejected", "Withdrawn", "Deferred", "Final", - "Active", "Draft") - -def consume_headers(directory='.'): - """Pull out metadata for every PEP in the specified directory and return - them in a list sorted by PEP name.""" - peps = [] - for file_name in os.listdir(directory): - if file_name.startswith('pep-') and file_name.endswith('.txt'): - peps.append(consume_pep(os.path.join(directory, file_name))) - peps.sort(key=lambda pep: pep['PEP']) - return peps - -def consume_pep(path): - """Consume the specified file as a PEP to get its metadata.""" - pep_info = {} - with open(path, 'rU') as pep_file: - try: - for line in pep_file: - if line == '\n': - break - elif line[1].isspace(): - type_ = parse_metadata(pep_info, line, type_) - else: - type_ = parse_metadata(pep_info, line) - except Exception: - print "In", pep_file - raise - if not 'PEP' in pep_info: - raise ValueError("PEP at file %s lacks a PEP number" % path) - if not 'Author' in pep_info: - raise ValueError("PEP %s is missing the Author field" % - pep_info['PEP']) - if len(pep_info['Author']) < 1: - raise ValueError("PEP %s is lacking authors" % pep_info['PEP']) - if pep_info['Type'] not in type_values: - raise ValueError("%s is an invalid Type value for PEP %s" % - (pep_info['Type'], pep_info['PEP'])) - if pep_info['Status'] not in status_values: - raise ValueError("%s is an invalid Status value for PEP %s" % - (pep_info['Status'], pep_info['PEP'])) - return pep_info - -def parse_metadata(pep_info, line, previous_type=None): - """Parse the given line for PEP metadata, adding on to existing metadata if - previous_type is specified, returning the last type of metadata handled.""" - if previous_type: - type_ = previous_type - data = line - else: - type_, data = line.split(':', 1) - type_ = type_.strip() - data = data.strip() - handler = handlers.get(type_, handle_generic) - result = handler(data) - if previous_type: - previous_data = pep_info[type_] - if not isinstance(previous_data, list): - previous_data = [previous_data] - pep_info[type_] = previous_data - previous_data.extend(result) - else: - pep_info[type_] = result - return type_ - -def handle_generic(data): - """Default handler for PEP metadata.""" - return data - -def handle_pep_num(data): - """Return the integer for the PEP number.""" - return int(data) - -def handle_author(data): - """Return a list of author names.""" - angled = r'(?P.+?) <.+?>' - paren = r'.+? \((?P.+?)\)' - simple = r'(?P[^,]+)' - author_list = [] - for regex in (angled, paren, simple): - # Watch out for commas separating multiple names. - regex += '(,\s+)?' - for match in re.finditer(regex, data): - author = match.group('author') - # Watch out for suffixes like 'Jr.' when they are comma-separated - # from the name and thus cause issues when *all* names are only - # separated by commas. - author = match.group('author') - if not author.partition(' ')[1] and author.endswith('.'): - prev_author = author_list.pop() - author = ', '.join([prev_author, author]) - author_list.append(author) - else: - # If authors were found then stop searching as only expect one - # style of author citation. - if author_list: - break - return author_list - -def handle_csv(data): - """Handle the Post-History.""" - return [value.strip() for value in data.split(',') if value] - -handlers = {'Author': handle_author, - 'PEP': handle_pep_num, - 'Post-History': handle_csv, - } - -def last_name(full_name, nicknames={}): - """Find the last name (or nickname) of a full name. - - If no last name (e.g, 'Aahz') then return the full name. If there is a - leading, lowercase portion to the last name (e.g., 'van' or 'von') then - include it. If there is a suffix (e.g., 'Jr.') that is appended through a - comma, then drop the suffix. - - """ - nickname = nicknames.get(full_name) - if nickname: - return nickname - no_suffix = full_name.partition(',')[0] - name_parts = no_suffix.split() - part_count = len(name_parts) - if part_count == 1 or part_count == 2: - return name_parts[-1] - else: - assert part_count > 2 - if name_parts[-2].islower(): - return ' '.join(name_parts[-2:]) - else: - return name_parts[-1] - -def sort_peps(peps): - """Sort PEPs into meta, informational, accepted, open, finished, empty, - and essentially dead.""" - meta = [] - info = [] - accepted = [] - open_ = [] - finished = [] - empty = [] - dead = [] - for pep in peps: - # Order of 'if' statement important. Key Status values take precedence - # over Type value, and vice-versa. - if pep['Status'] == 'Draft': - open_.append(pep) - elif pep['Status'] in ('Rejected', 'Withdrawn', 'Deferred', - 'Incomplete'): - dead.append(pep) - elif pep['Type'] == 'Process': - meta.append(pep) - elif pep['Type'] == 'Informational': - info.append(pep) - elif pep['Status'] == 'Accepted': - accepted.append(pep) - elif pep['Status'] == 'Final': - finished.append(pep) - return meta, info, accepted, open_, finished, empty, dead - -def write_pep(pep, output): - """Write PEP info to 'output'.""" - type_abbr = pep['Type'][0].upper() - status = pep['Status'] - if status in ('Draft', 'Active'): - status_abbr = ' ' - else: - status_abbr = status[0].upper() - number = str(pep['PEP']).rjust(4) - title = pep['Title'] - authors_list = [] - author_string = ', '.join(last_name(author, authors.nicknames) - for author in pep['Author']) - output.write(" %s%s %s %s %s\n" % - (type_abbr, status_abbr, number, title.ljust(44), - author_string)) - -def write_column_headers(output): - """Output the column headers for the PEP indices.""" - output.write('%s %s %s\n' % ("num".rjust(8), "title".ljust(44), "owner")) - output.write('%s %s %s\n' % ((len("num")*'-').rjust(8), - (len("title")*'-').ljust(44), len("owner")*'-')) - - - -if __name__ == '__main__': - from sys import argv, stdout - - if not argv[1:]: - path = '.' - else: - path = argv[1] - if os.path.isdir(path): - peps = consume_headers(path) - else: - peps = [consume_pep(path)] - - print header - print - print "Introduction" - print intro - print - print "Index by Category" - print - write_column_headers(stdout) - meta, info, accepted, open_, done, empty, dead = sort_peps(peps) - print - print " Meta-PEPs (PEPs about PEPs or Processs)" - print - for pep in meta: - write_pep(pep, stdout) - print - print " Other Informational PEPs" - print - for pep in info: - write_pep(pep, stdout) - print - print " Accepted PEPs (accepted; may not be implemented yet)" - print - for pep in accepted: - write_pep(pep, stdout) - print - print " Open PEPs (under consideration)" - print - for pep in open_: - write_pep(pep, stdout) - print - print " Finished PEPs (done, implemented in code repository)" - print - for pep in done: - write_pep(pep, stdout) - print - print " Empty PEPs (or containing only abstract)" - print - for pep in empty: - write_pep(pep, stdout) - print - print " Deferred, Abandoned, Withdrawn, and Rejected PEPs" - print - for pep in dead: - write_pep(pep, stdout) - print - print - print " Numerical Index" - print - write_column_headers(stdout) - prev_pep = 0 - for pep in peps: - if pep['PEP'] - prev_pep > 1: - print - write_pep(pep, stdout) - prev_pep = pep['PEP'] - print - print - print "Key" - print - for type_ in type_values: - print " %s - %s PEP" % (type_[0], type_) - print - for status in status_values: - print " %s - %s proposal" % (status[0], status) - - print - print - print "Owners" - print - # XXX - # * get "last, first I." of each name. - # * add nickname. - # * find longest name. - # * column headers. - # * name/email with a two-space separation between longest name and email. - print ' XXX' - print - print - print "References" - print - print references - print footer Added: sandbox/trunk/pep0/pep0/__init__.py ============================================================================== --- (empty file) +++ sandbox/trunk/pep0/pep0/__init__.py Sun Apr 15 05:21:46 2007 @@ -0,0 +1,117 @@ +"""Auto-generate PEP 0 (PEP index). + +Generating the PEP index is a multi-step process. To begin, you must first +parse the PEP files themselves, which in and of itself takes a couple of steps: + + 1. Parse metadata. + 2. Validate metadata. + +With the PEP information collected, to create the index itself you must: + + 1. Output static text. + 2.. Format an entry for the PEP. + 3. Output the PEP (both by category and numerical index). + +""" +from __future__ import absolute_import + +if __name__ == '__main__': + from pep0.parse import consume_headers, consume_pep + from pep0.pep import sort_peps, PEP + from pep0.output import write_column_headers, write_pep + from pep0.statictext import header, intro, references, footer + + import os + from sys import argv, stdout + + if not argv[1:]: + path = '.' + else: + path = argv[1] + if os.path.isdir(path): + peps = consume_headers(path) + else: + peps = [consume_pep(path)] + + print header + print + print "Introduction" + print intro + print + print "Index by Category" + print + write_column_headers(stdout) + meta, info, accepted, open_, done, empty, dead = sort_peps(peps) + print + print " Meta-PEPs (PEPs about PEPs or Processs)" + print + for pep in meta: + write_pep(pep, stdout) + print + print " Other Informational PEPs" + print + for pep in info: + write_pep(pep, stdout) + print + print " Accepted PEPs (accepted; may not be implemented yet)" + print + for pep in accepted: + write_pep(pep, stdout) + print + print " Open PEPs (under consideration)" + print + for pep in open_: + write_pep(pep, stdout) + print + print " Finished PEPs (done, implemented in code repository)" + print + for pep in done: + write_pep(pep, stdout) + print + print " Empty PEPs (or containing only abstract)" + print + for pep in empty: + write_pep(pep, stdout) + print + print " Deferred, Abandoned, Withdrawn, and Rejected PEPs" + print + for pep in dead: + write_pep(pep, stdout) + print + print + print " Numerical Index" + print + write_column_headers(stdout) + prev_pep = 0 + for pep in peps: + if pep['PEP'] - prev_pep > 1: + print + write_pep(pep, stdout) + prev_pep = pep['PEP'] + print + print + print "Key" + print + for type_ in PEP.type_values: + print " %s - %s PEP" % (type_[0], type_) + print + for status in PEP.status_values: + print " %s - %s proposal" % (status[0], status) + + print + print + print "Owners" + print + # XXX + # * get "last, first I." of each name. + # * add nickname. + # * find longest name. + # * column headers. + # * name/email with a two-space separation between longest name and email. + print ' XXX' + print + print + print "References" + print + print references + print footer Added: sandbox/trunk/pep0/pep0/authors.py ============================================================================== --- (empty file) +++ sandbox/trunk/pep0/pep0/authors.py Sun Apr 15 05:21:46 2007 @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +email_addresses = { + 'Aahz' : 'aahz at pobox.com', + 'James C. Ahlstrom' : 'jim at interet.com', + 'Jim Althoff' : 'james_althoff at i2.com', + 'Kevin Altis' : 'altis at semi-retired.com', + 'David Ascher' : 'davida at activestate.com', + 'Peter Astrand' : 'astrand at lysator.liu.se', + 'Carl Banks' : 'pythondev at aerojockey.com', + 'Paul Barrett' : 'barrett at stsci.edu', + 'Facundo Batista' : 'facundo at taniquetil.com.ar', + 'Anthony Baxter' : 'anthony at interlink.com.au', + 'Thomas Bellman' : 'bellman+pep-divmod at lysator.liu.se', + 'Steven Bethard' : 'steven.bethard at gmail.com', + 'Georg Brandl' : 'g.brandl at gmx.net', + 'Brett Cannon' : 'brett at python.org', + 'Josiah Carlson' : 'jcarlson at uci.edu', + 'W Isaac Carroll' : 'icarroll at pobox.com', + 'Nick Coghlan' : 'ncoghlan at gmail.com', + 'Dave Cole' : 'djc at object-craft.com.au', + 'Christopher Craig' : 'python-pep at ccraig.org', + 'Laura Creighton' : 'lac at strakt.com', + 'Walter D?rwald' : '', + 'Fred L. Drake, Jr.' : 'fdrake at acm.org', + 'Michael P. Dubner' : 'dubnerm at mindless.com', + 'Paul F. Dubois' : 'paul at pfdubois.com', + 'Phillip J. Eby' : 'pje at telecommunity.com', + 'Micah Elliott' : 'mde at tracos.org', + 'Jeff Epler' : 'jepler at unpythonic.net', + 'David Eppstein' : 'eppstein at ics.uci.edu', + 'Clark C. Evans' : 'cce at clarkevans.com', + 'Greg Ewing' : 'greg at cosc.canterbury.ac.nz', + 'Martijn Faassen' : 'faassen at infrae.com', + 'Ben Finney' : 'ben+python at benfinney.id.au', + 'Fr?d?ric B. Giacometti' : 'fred at arakne.com', + 'Scott Gilbert' : 'xscottg at yahoo.com', + 'David Goodger' : 'goodger at python.org', + 'Grant Griffin' : 'g2 at iowegian.com', + 'Mark Hammond' : 'mhammond at skippinet.com.au', + 'Peter Harris' : 'scav at blueyonder.co.uk', + 'Thomas Heller' : 'theller at python.net', + 'Magnus Lie Hetland' : 'magnus at hetland.org', + 'Raymond D. Hettinger' : 'python at rcn.com', + 'Neil Hodgson' : 'neilh at scintilla.org', + 'Michael Hudson' : 'mwh at python.net', + 'Jeremy Hylton' : 'jeremy at zope.com', + 'Jack Jansen' : 'jack at cwi.nl', + 'Jim Jewett' : 'jimjjewett at users.sourceforge.net', + 'Richard Jones' : 'richard at mechanicalcat.net', + 'Stepan Koltsov' : 'yozh at mx1.ru', + 'A.M. Kuchling' : 'amk at amk.ca', + 'Marc-Andre Lemburg' : 'mal at lemburg.com', + 'Gregory Lielens' : 'gregory.lielens at fft.be', + 'Bj?rn Lindqvist' : 'bjourne at gmail.com', + 'Martin von L?wis' : 'loewis at informatik.hu-berlin.de', + 'Tony Lownds' : 'tony at pagedna.com', + 'Alex Martelli' : 'aleax at aleax.it', + 'Andrew McClelland' : 'eternalsquire at comcast.net', + 'Gordon McMillan' : 'gmcm at hypernet.com', + 'Andrew McNamara' : 'andrewm at object-craft.com.au', + 'Trent Mick' : 'trentm at activestate.com', + 'Mike Meyer' : 'mwm at mired.org', + 'Skip Montanaro' : 'skip at pobox.com', + 'Paul Moore' : 'gustav at morpheus.demon.co.uk', + 'Ben North' : 'ben at redfrontdoor.org', + 'Neal Norwitz' : 'nnorwitz at gmail.com', + 'Travis Oliphant' : 'oliphant at ee.byu.edu', + 'Jason Orendorff' : 'jason.orendorff at gmail.com', + 'Samuele Pedroni' : 'pedronis at python.org', + 'Michel Pelletier' : 'michel at users.sourceforge.net', + 'Tim Peters' : 'tim at zope.com', + 'Jason Petrone' : 'jp at demonseed.net', + 'Paul Prescod' : 'paul at prescod.net', + 'Terry Reedy' : 'tjreedy at udel.edu', + 'Sean Reifschneider' : 'jafo-pep at tummy.com', + 'Christian R. Reis' : 'kiko at async.com.br', + 'Jonathan Riehl' : 'jriehl at spaceship.com', + 'Andr? Roberge' : 'andre.roberge at gmail.com', + 'Guido van Rossum' : 'guido at python.org', + 'Just van Rossum' : 'just at letterror.com', + 'Vinay Sajip' : 'vinay_sajip at red-dove.com', + 'Neil Schemenauer' : 'nas at arctrix.com', + 'Peter Schneider-Kamp' : 'nowonder at nowonder.de', + 'Jiwon Seo' : 'seojiwon at gmail.com', + 'Kevin D. Smith' : 'Kevin.Smith at theMorgue.org', + 'Greg Stein' : 'gstein at lyra.org', + 'Daniel Stutzbach' : 'daniel.stutzbach at gmail.com', + 'Roman Suzi' : 'rnd at onego.ru', + 'Talin' : 'talin at acm.org', + 'Steven Taschuk' : 'staschuk at telusplanet.net', + 'Oren Tirosh' : 'oren at hishome.net', + 'Mike Verdone' : 'mike.verdone at gmail.com', + 'Gregory R. Warnes' : 'warnes at users.sourceforge.net', + 'Barry Warsaw' : 'barry at python.org', + 'Terence Way' : 'terry at wayforward.net', + 'Cliff Wells' : 'LogiplexSoftware at earthlink.net', + 'Greg Wilson' : 'gvwilson at ddj.com', + 'Collin Winter' : 'collinw at gmail.com', + 'Thomas Wouters' : 'thomas at python.org', + 'Ka-Ping Yee' : 'ping at zesty.ca', + 'Moshe Zadka' : 'moshez at zadka.site.co.il', + 'Huaiyu Zhu' : 'hzhu at users.sourceforge.net', +} + +nicknames = { + 'Guido van Rossum' : 'GvR', + 'Just van Rossum' : 'JvR', +} Added: sandbox/trunk/pep0/pep0/output.py ============================================================================== --- (empty file) +++ sandbox/trunk/pep0/pep0/output.py Sun Apr 15 05:21:46 2007 @@ -0,0 +1,58 @@ +from . import authors +from .pep import last_name + +indent = ' ' + +def make_entry(type_, status, number, title, owners): + """Return the string representation for a PEP entry (or anything that is + similarly formatted. + + If type_ or status have values of None they are filled in with whitespace. + All arguments are expected to be valid. + + """ + entry = [indent] + # Type. + if type_: + entry.append(type_[0].upper()) + else: + entry.append(' ') + # Status. + if status and status not in ('Active', 'Draft'): + entry.append(type_[0].upper()) + else: + entry.append(' ') + # Number. + entry.append(str(number).ljust(4)) + # Title. + entry.append(title.rjust(44)) + # owners. + entry.append(', '.join(last_name(owner) for owner in owners)) + + # Indent, Type, Statue, Number, Title, Owners. + return "%s%s%s %s %s %s" % entry + +def write_pep(pep, output): + """Write PEP info to 'output'.""" + type_abbr = pep['Type'][0].upper() + status = pep['Status'] + if status in ('Draft', 'Active'): + status_abbr = ' ' + else: + status_abbr = status[0].upper() + number = str(pep['PEP']).rjust(4) + title = pep['Title'] + authors_list = [] + author_string = ', '.join(last_name(author, authors.nicknames) + for author in pep['Author']) + output.write(" %s%s %s %s %s\n" % + (type_abbr, status_abbr, number, title.ljust(44), + author_string)) + +def write_column_headers(output): + """Output the column headers for the PEP indices.""" + output.write('%s %s %s\n' % ("num".rjust(8), "title".ljust(44), "owner")) + output.write('%s %s %s\n' % ((len("num")*'-').rjust(8), + (len("title")*'-').ljust(44), len("owner")*'-')) + + Added: sandbox/trunk/pep0/pep0/parse.py ============================================================================== --- (empty file) +++ sandbox/trunk/pep0/pep0/parse.py Sun Apr 15 05:21:46 2007 @@ -0,0 +1,111 @@ +from __future__ import with_statement +from .pep import PEP + +import os +import re + +def consume_headers(directory='.'): + """Pull out metadata for every PEP in the specified directory and return + them in a list sorted by PEP name.""" + peps = [] + for file_name in os.listdir(directory): + if file_name.startswith('pep-') and file_name.endswith('.txt'): + peps.append(consume_pep(os.path.join(directory, file_name))) + peps.sort(key=lambda pep: pep['PEP']) + return peps + +def consume_pep(path): + """Consume the specified file as a PEP to get its metadata.""" + pep_info = {} + with open(path, 'rU') as pep_file: + try: + for line in pep_file: + if line == '\n': + break + elif line[1].isspace(): + type_ = parse_metadata(pep_info, line, type_) + else: + type_ = parse_metadata(pep_info, line) + except Exception: + print "*** In", pep_file + raise + if not 'PEP' in pep_info: + raise ValueError("PEP at file %s lacks a PEP number" % path) + if not 'Author' in pep_info: + raise ValueError("PEP %s is missing the Author field" % + pep_info['PEP']) + if len(pep_info['Author']) < 1: + raise ValueError("PEP %s is lacking authors" % pep_info['PEP']) + if pep_info['Type'] not in PEP.type_values: + raise ValueError("%s is an invalid Type value for PEP %s" % + (pep_info['Type'], pep_info['PEP'])) + if pep_info['Status'] not in PEP.status_values: + raise ValueError("%s is an invalid Status value for PEP %s" % + (pep_info['Status'], pep_info['PEP'])) + return pep_info + +def parse_metadata(pep_info, line, previous_type=None): + """Parse the given line for PEP metadata, adding on to existing metadata if + previous_type is specified, returning the last type of metadata handled.""" + if previous_type: + type_ = previous_type + data = line + else: + type_, data = line.split(':', 1) + type_ = type_.strip() + data = data.strip() + handler = handlers.get(type_, handle_generic) + result = handler(data) + if previous_type: + previous_data = pep_info[type_] + if not isinstance(previous_data, list): + previous_data = [previous_data] + pep_info[type_] = previous_data + previous_data.extend(result) + else: + pep_info[type_] = result + return type_ + +def handle_generic(data): + """Default handler for PEP metadata.""" + return data + +def handle_pep_num(data): + """Return the integer for the PEP number.""" + return int(data) + +def handle_author(data): + """Return a list of author names.""" + angled = r'(?P.+?) <.+?>' + paren = r'.+? \((?P.+?)\)' + simple = r'(?P[^,]+)' + author_list = [] + for regex in (angled, paren, simple): + # Watch out for commas separating multiple names. + regex += '(,\s+)?' + for match in re.finditer(regex, data): + author = match.group('author') + # Watch out for suffixes like 'Jr.' when they are comma-separated + # from the name and thus cause issues when *all* names are only + # separated by commas. + author = match.group('author') + if not author.partition(' ')[1] and author.endswith('.'): + prev_author = author_list.pop() + author = ', '.join([prev_author, author]) + author_list.append(author) + else: + # If authors were found then stop searching as only expect one + # style of author citation. + if author_list: + break + return author_list + +def handle_csv(data): + """Handle the Post-History.""" + return [value.strip() for value in data.split(',') if value] + +handlers = {'Author': handle_author, + 'PEP': handle_pep_num, + 'Post-History': handle_csv, + } + Added: sandbox/trunk/pep0/pep0/pep.py ============================================================================== --- (empty file) +++ sandbox/trunk/pep0/pep0/pep.py Sun Apr 15 05:21:46 2007 @@ -0,0 +1,76 @@ +class PEP(object): + + """Representation of PEPs.""" + + type_values = ("Standards Track", "Informational", "Process") + # Active and Draft are not listed in the index. + status_values = ("Accepted", "Rejected", "Withdrawn", "Deferred", "Final", + "Active", "Draft") + + def __init__(self, metadata_dict): + """Init object based on dict containing metadata from a file.""" + pass + + def validate(self): + """Validate that the instance data.""" + pass + + def __str__(self): + """Return the line entry for the PEP.""" + return '' + pass + + +def last_name(full_name, nicknames={}): + """Find the last name (or nickname) of a full name. + + If no last name (e.g, 'Aahz') then return the full name. If there is a + leading, lowercase portion to the last name (e.g., 'van' or 'von') then + include it. If there is a suffix (e.g., 'Jr.') that is appended through a + comma, then drop the suffix. + + """ + nickname = nicknames.get(full_name) + if nickname: + return nickname + no_suffix = full_name.partition(',')[0] + name_parts = no_suffix.split() + part_count = len(name_parts) + if part_count == 1 or part_count == 2: + return name_parts[-1] + else: + assert part_count > 2 + if name_parts[-2].islower(): + return ' '.join(name_parts[-2:]) + else: + return name_parts[-1] + +def sort_peps(peps): + """Sort PEPs into meta, informational, accepted, open, finished, empty, + and essentially dead.""" + meta = [] + info = [] + accepted = [] + open_ = [] + finished = [] + empty = [] + dead = [] + for pep in peps: + # Order of 'if' statement important. Key Status values take precedence + # over Type value, and vice-versa. + if pep['Status'] == 'Draft': + open_.append(pep) + elif pep['Status'] in ('Rejected', 'Withdrawn', 'Deferred', + 'Incomplete'): + dead.append(pep) + elif pep['Type'] == 'Process': + meta.append(pep) + elif pep['Type'] == 'Informational': + info.append(pep) + elif pep['Status'] == 'Accepted': + accepted.append(pep) + elif pep['Status'] == 'Final': + finished.append(pep) + return meta, info, accepted, open_, finished, empty, dead + + Added: sandbox/trunk/pep0/pep0/statictext.py ============================================================================== --- (empty file) +++ sandbox/trunk/pep0/pep0/statictext.py Sun Apr 15 05:21:46 2007 @@ -0,0 +1,40 @@ +# Don't start on a new line to make easier to read as that would cause output to +# start on a blank line. +header = """PEP: 0 +Title: Index of Python Enhancement Proposals (PEPs) +Version: $Revision$ +Last-Modified: $Date$ +Author: David Goodger , + Barry A. Warsaw +Status: Active +Type: Informational +Created: 13-Jul-2000 +""" + +intro = """ + The PEP contains the index of all Python Enhancement Proposals, + known as PEPs. PEP numbers are assigned by the PEP Editor, and + once assigned are never changed. The SVN history[1] of the PEP + texts represent their historical record. + + The BDFL maintains his own Pronouncements page[2] at + http://www.python.org/doc/essays/pepparade.html which contains his + musings on the various outstanding PEPs. +""" + +references = """ + [1] View PEP history online + http://svn.python.org/projects/peps/trunk/ + + [2] The Benevolent Dictator For Life's Parade of PEPs + http://www.python.org/doc/essays/pepparade.html +""" + +footer = """ +Local Variables: +mode: indented-text +indent-tabs-mode: nil +sentence-end-double-space: t +fill-column: 70 +coding: utf-8 +End:""" Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Sun Apr 15 05:21:46 2007 @@ -8,6 +8,8 @@ class HandlerTests(unittest.TestCase): + """Test the PEP field handlers for parsing data.""" + def test_handle_generic(self): # Identity function. for data in ('spam', 'spam,', '', 'spam, monty'): @@ -54,6 +56,8 @@ class ParseMetaDataTests(unittest.TestCase): + """Test the parsing of the headers of PEPs.""" + def test_parse_known_formats(self): # Handle specific metadata format types. assert "PEP" in pep0.handlers @@ -88,6 +92,34 @@ self.failUnlessEqual(info[type_][1], data) +class PEPClassTests(unittest.TestCase): + + """Test the PEP class.""" + + def test_valid_init(self): + # Make sure that a PEP instance can be created from a dict with valid + # entries. + pass + + # Number cannot be invalid as that is checked during parsing of the PEP. + + def test_invalid_status(self): + # Invalid Status entry raises an exception. + pass + + def test_invalid_type(self): + # Invalid type should raise an exception. + pass + + def test_invalid_authors(self): + # There should be at least one author. + pass + + def test_str(self): + # String representation of the PEP. + pass + + @contextmanager def test_file(path): try: @@ -101,6 +133,8 @@ class ConsumePepTests(unittest.TestCase): + """Test the reading and parsing of a PEP file.""" + def test_single_line(self): # Test a PEP that only has a single line of metadata. type_ = 'Spam' @@ -143,8 +177,66 @@ self.failUnless('Post-History' in metadata) self.failUnlessEqual(metadata['Post-History'], dates) - -class OutputTests(unittest.TestCase): + def test_missing_fields(self): + # Missing key fields should raise ValueError. + # PEP + # Author + # Type + # Status + pass + + def test_pep_field(self): + # PEP field should only contain a number. + pass + + def test_author_field(self): + # Author field should have at least a single author. + pass + + def test_type_field(self): + # Type field should contain only a valid value. + pass + + def test_status_field(self): + # Status field should contain only a valid value. + pass + + +class EntryOutputTests(unittest.TestCase): + + """Tests for single-line output into the index.""" + + def test_make_entry_type(self): + # Test handling of type_ argument. + pass + + def test_make_entry_status(self): + # make_entry's status argument. + pass + + def test_make_entry_number(self): + # make_entry's number argument. + pass + + def test_make_entry_number(self): + # make_entry's title argument. + pass + + def test_make_entry_title(self): + # make_entry's title argument. + pass + + def test_make_entry_owners(self): + # make_entry's owners argument. + pass + + def test_make_entry_column_headers(self): + # Should be able to output column headers properly. + pass + + def test_make_entry_underline(self): + # Underlining of column headers should be okay. + pass def test_author_last_name(self): # Test that last names are discovered properly. @@ -173,8 +265,9 @@ test_support.run_unittest( HandlerTests, ParseMetaDataTests, + PEPClassTests, ConsumePepTests, - OutputTests, + EntryOutputTests, ) From python-checkins at python.org Sun Apr 15 05:31:55 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2007 05:31:55 +0200 (CEST) Subject: [Python-checkins] r54833 - in sandbox/trunk/pep0: TODO pep0/output.py pep0/parse.py pep0/pep.py Message-ID: <20070415033155.907731E4004@bag.python.org> Author: brett.cannon Date: Sun Apr 15 05:31:50 2007 New Revision: 54833 Modified: sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0/output.py sandbox/trunk/pep0/pep0/parse.py sandbox/trunk/pep0/pep0/pep.py Log: Add comments about what needs to be done to complete refactoring. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Sun Apr 15 05:31:50 2007 @@ -1,3 +1,10 @@ +* Handle XXX comments: + + __init__ + + parse + + pep + + output + + Update test_pep0 to reflect refactoring. + Functionality to add -------------------- Modified: sandbox/trunk/pep0/pep0/output.py ============================================================================== --- sandbox/trunk/pep0/pep0/output.py (original) +++ sandbox/trunk/pep0/pep0/output.py Sun Apr 15 05:31:50 2007 @@ -1,3 +1,11 @@ +"""Code to handle the output of PEP 0. + +XXX + * Move output code from __init__ to here. + * Move PEP sorting to here. + * Move last name code to here? + +""" from . import authors from .pep import last_name Modified: sandbox/trunk/pep0/pep0/parse.py ============================================================================== --- sandbox/trunk/pep0/pep0/parse.py (original) +++ sandbox/trunk/pep0/pep0/parse.py Sun Apr 15 05:31:50 2007 @@ -1,3 +1,12 @@ +"""Parse the metadata from a PEP file. + +XXX + * Remove metadata validation and move to pep class. + + Still validate PEP number is an integer (it's needed for error + reporting from this point forward). + + Validate PEP number matches number in file name. + +""" from __future__ import with_statement from .pep import PEP Modified: sandbox/trunk/pep0/pep0/pep.py ============================================================================== --- sandbox/trunk/pep0/pep0/pep.py (original) +++ sandbox/trunk/pep0/pep0/pep.py Sun Apr 15 05:31:50 2007 @@ -1,3 +1,10 @@ +"""Code for handling object representation of a PEP. + +XXX + * Flesh out PEP class. + +""" + class PEP(object): """Representation of PEPs.""" From python-checkins at python.org Sun Apr 15 05:36:59 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2007 05:36:59 +0200 (CEST) Subject: [Python-checkins] r54834 - sandbox/trunk/pep0/pep0/parse.py Message-ID: <20070415033659.5713E1E4003@bag.python.org> Author: brett.cannon Date: Sun Apr 15 05:36:58 2007 New Revision: 54834 Modified: sandbox/trunk/pep0/pep0/parse.py Log: Explain in more detail what pep0.parse is expected to do. Modified: sandbox/trunk/pep0/pep0/parse.py ============================================================================== --- sandbox/trunk/pep0/pep0/parse.py (original) +++ sandbox/trunk/pep0/pep0/parse.py Sun Apr 15 05:36:58 2007 @@ -1,5 +1,13 @@ """Parse the metadata from a PEP file. +Parsing consists of several steps: + + * Detecting and reading all lines of text relating to metadata. + * Concatenating multi-line metadata for a single field into a single line. + * Validate PEP number (needed for future error reporting). + + Must be an integer. + + Must match file name. + XXX * Remove metadata validation and move to pep class. + Still validate PEP number is an integer (it's needed for error From python-checkins at python.org Mon Apr 16 08:12:03 2007 From: python-checkins at python.org (neal.norwitz) Date: Mon, 16 Apr 2007 08:12:03 +0200 (CEST) Subject: [Python-checkins] r54836 - python/branches/release25-maint/Python/sysmodule.c Message-ID: <20070416061203.4C8601E4011@bag.python.org> Author: neal.norwitz Date: Mon Apr 16 08:12:02 2007 New Revision: 54836 Modified: python/branches/release25-maint/Python/sysmodule.c Log: SF #1701207: svnversion_init assertion failed Revert bogus asserts (added to the wrong place) from rev 52501. Approved by Anthony. Modified: python/branches/release25-maint/Python/sysmodule.c ============================================================================== --- python/branches/release25-maint/Python/sysmodule.c (original) +++ python/branches/release25-maint/Python/sysmodule.c Mon Apr 16 08:12:02 2007 @@ -997,8 +997,6 @@ } else if (istag || strncmp(br_start, "branches", 8) == 0) { len = br_end2 - br_start; - assert(len >= 13); - assert(len < (sizeof(patchlevel_revision) - 13)); strncpy(branch, br_start, len); branch[len] = '\0'; From python-checkins at python.org Mon Apr 16 08:19:34 2007 From: python-checkins at python.org (neal.norwitz) Date: Mon, 16 Apr 2007 08:19:34 +0200 (CEST) Subject: [Python-checkins] r54837 - python/branches/release25-maint/PC/getpathp.c Message-ID: <20070416061934.9A3CA1E4004@bag.python.org> Author: neal.norwitz Date: Mon Apr 16 08:19:32 2007 New Revision: 54837 Modified: python/branches/release25-maint/PC/getpathp.c Log: Revert 54815 for 2.5.1 release. Can be applied after 2.5 branch is unfrozen. Modified: python/branches/release25-maint/PC/getpathp.c ============================================================================== --- python/branches/release25-maint/PC/getpathp.c (original) +++ python/branches/release25-maint/PC/getpathp.c Mon Apr 16 08:19:32 2007 @@ -650,7 +650,7 @@ start of the path in question - even if this is one character before the start of the buffer */ - while (look >= module_search_path && *look != DELIM) + while (*look != DELIM && look >= module_search_path) look--; nchars = lookEnd-look; strncpy(lookBuf, look+1, nchars); From python-checkins at python.org Mon Apr 16 08:19:54 2007 From: python-checkins at python.org (neal.norwitz) Date: Mon, 16 Apr 2007 08:19:54 +0200 (CEST) Subject: [Python-checkins] r54838 - in python/branches/release25-maint: Objects/frameobject.c Python/ceval.c Message-ID: <20070416061954.C41A11E4004@bag.python.org> Author: neal.norwitz Date: Mon Apr 16 08:19:52 2007 New Revision: 54838 Modified: python/branches/release25-maint/Objects/frameobject.c python/branches/release25-maint/Python/ceval.c Log: Revert 54813 for 2.5.1 release. Can be applied after 2.5 branch is unfrozen. Modified: python/branches/release25-maint/Objects/frameobject.c ============================================================================== --- python/branches/release25-maint/Objects/frameobject.c (original) +++ python/branches/release25-maint/Objects/frameobject.c Mon Apr 16 08:19:52 2007 @@ -68,7 +68,7 @@ int new_lineno = 0; /* The new value of f_lineno */ int new_lasti = 0; /* The new value of f_lasti */ int new_iblock = 0; /* The new value of f_iblock */ - unsigned char *code = NULL; /* The bytecode for the frame... */ + char *code = NULL; /* The bytecode for the frame... */ Py_ssize_t code_len = 0; /* ...and its length */ char *lnotab = NULL; /* Iterating over co_lnotab */ Py_ssize_t lnotab_len = 0; /* (ditto) */ @@ -85,7 +85,7 @@ int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */ int in_finally[CO_MAXBLOCKS]; /* (ditto) */ int blockstack_top = 0; /* (ditto) */ - unsigned char setup_op = 0; /* (ditto) */ + int setup_op = 0; /* (ditto) */ /* f_lineno must be an integer. */ if (!PyInt_Check(p_new_lineno)) { Modified: python/branches/release25-maint/Python/ceval.c ============================================================================== --- python/branches/release25-maint/Python/ceval.c (original) +++ python/branches/release25-maint/Python/ceval.c Mon Apr 16 08:19:52 2007 @@ -662,7 +662,7 @@ #define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \ lltrace && prtrace(TOP(), "stackadj")); \ assert(STACK_LEVEL() <= co->co_stacksize); } -#define EXT_POP(STACK_POINTER) (lltrace && prtrace((STACK_POINTER)[-1], "ext_pop"), *--(STACK_POINTER)) +#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER)) #else #define PUSH(v) BASIC_PUSH(v) #define POP() BASIC_POP() From python-checkins at python.org Mon Apr 16 08:20:14 2007 From: python-checkins at python.org (neal.norwitz) Date: Mon, 16 Apr 2007 08:20:14 +0200 (CEST) Subject: [Python-checkins] r54839 - python/branches/release25-maint/Lib/test/test_pty.py Message-ID: <20070416062014.E04DB1E4007@bag.python.org> Author: neal.norwitz Date: Mon Apr 16 08:20:14 2007 New Revision: 54839 Modified: python/branches/release25-maint/Lib/test/test_pty.py Log: Revert 54805 for 2.5.1 release. Can be applied after 2.5 branch is unfrozen. Modified: python/branches/release25-maint/Lib/test/test_pty.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_pty.py (original) +++ python/branches/release25-maint/Lib/test/test_pty.py Mon Apr 16 08:20:14 2007 @@ -115,24 +115,6 @@ os._exit(4) else: debug("Waiting for child (%d) to finish."%pid) - # In verbose mode, we have to consume the debug output from the child or - # the child will block, causing this test to hang in the parent's - # waitpid() call. The child blocks after a platform-dependent amount of - # data is written to its fd. On Linux 2.6, it's 4000 bytes and the child - # won't block, but on OS X even the small writes in the child above will - # block it. Also on Linux, the read() will throw an OSError (input/output - # error) when it tries to read past the end of the buffer but the child's - # already exited, so catch and discard those exceptions. It's not worth - # checking for EIO. - while True: - try: - data = os.read(master_fd, 80) - except OSError: - break - if not data: - break - sys.stdout.write(data.replace('\r\n', '\n')) - ##line = os.read(master_fd, 80) ##lines = line.replace('\r\n', '\n').split('\n') ##if False and lines != ['In child, calling os.setsid()', From nnorwitz at gmail.com Mon Apr 16 08:22:08 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sun, 15 Apr 2007 23:22:08 -0700 Subject: [Python-checkins] r54805 - python/branches/release25-maint/Lib/test/test_pty.py In-Reply-To: References: <20070413124313.BFJ16741@ms09.lnh.mail.rcn.net> Message-ID: On 4/13/07, Barry Warsaw wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > On Apr 13, 2007, at 12:43 PM, Raymond Hettinger wrote: > > > I thought the 25 maint branch was closed until a few days after the > > release-candidate goes final. If it is open, let me know, I've got > > more fixes to apply. > > I don't know, maybe it is. This one's extremely low risk as it only > affects certain platforms when test_pty is run verbosely. But if it > ain't cool, I'll back it out and re-apply after 2.5.1 final. We're trying to be safe and minimize the changes potential breakage. I backed out this change. Please re-apply after 2.5 branch is unfrozen. n From buildbot at python.org Mon Apr 16 08:53:02 2007 From: buildbot at python.org (buildbot at python.org) Date: Mon, 16 Apr 2007 06:53:02 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP 2.5 Message-ID: <20070416065302.BC64C1E4004@bag.python.org> The Buildbot has detected a new failure of x86 XP 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%25202.5/builds/197 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: neal.norwitz Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_profilehooks sincerely, -The Buildbot From python-checkins at python.org Mon Apr 16 08:59:17 2007 From: python-checkins at python.org (neal.norwitz) Date: Mon, 16 Apr 2007 08:59:17 +0200 (CEST) Subject: [Python-checkins] r54840 - in python/branches/release25-maint: Lib/test/test_dict.py Misc/NEWS Objects/dictobject.c Message-ID: <20070416065917.99C771E4004@bag.python.org> Author: neal.norwitz Date: Mon Apr 16 08:59:13 2007 New Revision: 54840 Modified: python/branches/release25-maint/Lib/test/test_dict.py python/branches/release25-maint/Misc/NEWS python/branches/release25-maint/Objects/dictobject.c Log: Revert SF #1615701 (rev 53655): dict.update() does *not* call __getitem__() or keys() if subclassed. This is to remain consistent with 2.5. See discussion here: http://mail.python.org/pipermail/python-dev/2007-April/072565.html Modified: python/branches/release25-maint/Lib/test/test_dict.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_dict.py (original) +++ python/branches/release25-maint/Lib/test/test_dict.py Mon Apr 16 08:59:13 2007 @@ -189,14 +189,6 @@ self.assertRaises(ValueError, {}.update, [(1, 2, 3)]) - # SF #1615701: make d.update(m) honor __getitem__() and keys() in dict subclasses - class KeyUpperDict(dict): - def __getitem__(self, key): - return key.upper() - d.clear() - d.update(KeyUpperDict.fromkeys('abc')) - self.assertEqual(d, {'a':'A', 'b':'B', 'c':'C'}) - def test_fromkeys(self): self.assertEqual(dict.fromkeys('abc'), {'a':None, 'b':None, 'c':None}) d = {} Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Mon Apr 16 08:59:13 2007 @@ -4,6 +4,18 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 2.5.1? +============================= + +*Release date: XX-APR-2007* + +Core and builtins +----------------- + +- Revert SF #1615701: dict.update() does *not* call __getitem__() or keys() + if subclassed. This is to remain consistent with 2.5. + + What's New in Python 2.5.1c1? ============================= Modified: python/branches/release25-maint/Objects/dictobject.c ============================================================================== --- python/branches/release25-maint/Objects/dictobject.c (original) +++ python/branches/release25-maint/Objects/dictobject.c Mon Apr 16 08:59:13 2007 @@ -1352,7 +1352,7 @@ return -1; } mp = (dictobject*)a; - if (PyDict_CheckExact(b)) { + if (PyDict_Check(b)) { other = (dictobject*)b; if (other == mp || other->ma_used == 0) /* a.update(a) or a.update({}); nothing to do */ From python-checkins at python.org Mon Apr 16 09:37:57 2007 From: python-checkins at python.org (neal.norwitz) Date: Mon, 16 Apr 2007 09:37:57 +0200 (CEST) Subject: [Python-checkins] r54841 - python/trunk/Python/sysmodule.c Message-ID: <20070416073757.411781E4004@bag.python.org> Author: neal.norwitz Date: Mon Apr 16 09:37:55 2007 New Revision: 54841 Modified: python/trunk/Python/sysmodule.c Log: SF #1701207, Fix bogus assertion (and test it!) Modified: python/trunk/Python/sysmodule.c ============================================================================== --- python/trunk/Python/sysmodule.c (original) +++ python/trunk/Python/sysmodule.c Mon Apr 16 09:37:55 2007 @@ -997,8 +997,6 @@ } else if (istag || strncmp(br_start, "branches", 8) == 0) { len = br_end2 - br_start; - assert(len >= 13); - assert(len < (sizeof(patchlevel_revision) - 13)); strncpy(branch, br_start, len); branch[len] = '\0'; @@ -1017,6 +1015,8 @@ svn_revision = svnversion; else if (istag) { len = strlen(_patchlevel_revision); + assert(len >= 13); + assert(len < (sizeof(patchlevel_revision) + 13)); strncpy(patchlevel_revision, _patchlevel_revision + 11, len - 13); patchlevel_revision[len - 13] = '\0'; From buildbot at python.org Mon Apr 16 10:50:32 2007 From: buildbot at python.org (buildbot at python.org) Date: Mon, 16 Apr 2007 08:50:32 +0000 Subject: [Python-checkins] buildbot warnings in g4 osx.4 2.5 Message-ID: <20070416085032.D7C7F1E4014@bag.python.org> The Buildbot has detected a new failure of g4 osx.4 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/g4%2520osx.4%25202.5/builds/307 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: neal.norwitz Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_logging sincerely, -The Buildbot From buildbot at python.org Mon Apr 16 12:53:21 2007 From: buildbot at python.org (buildbot at python.org) Date: Mon, 16 Apr 2007 10:53:21 +0000 Subject: [Python-checkins] buildbot warnings in hppa Ubuntu dapper trunk Message-ID: <20070416105321.E3DBE1E4004@bag.python.org> The Buildbot has detected a new failure of hppa Ubuntu dapper trunk. Full details are available at: http://www.python.org/dev/buildbot/all/hppa%2520Ubuntu%2520dapper%2520trunk/builds/162 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: neal.norwitz Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From barry at python.org Mon Apr 16 13:54:00 2007 From: barry at python.org (Barry Warsaw) Date: Mon, 16 Apr 2007 07:54:00 -0400 Subject: [Python-checkins] r54805 - python/branches/release25-maint/Lib/test/test_pty.py In-Reply-To: <461FEF11.4020100@v.loewis.de> References: <20070413124313.BFJ16741@ms09.lnh.mail.rcn.net> <461FEF11.4020100@v.loewis.de> Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Apr 13, 2007, at 4:58 PM, Martin v. L?wis wrote: >> I don't know, maybe it is. This one's extremely low risk as it only >> affects certain platforms when test_pty is run verbosely. But if it >> ain't cool, I'll back it out and re-apply after 2.5.1 final. > > Please back it out. If there are changes to the branch, we would have > to create another release candidate (IMO). I see Neal did already... thanks Neal. I was away for most of the weekend. Cheers, - -Barry -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Darwin) iQCVAwUBRiNj3XEjvBPtnXfVAQLgfQP+KVKtGkEzZpo8Bjhlo6w7zII5oQdo9pDy L18n2OjcJyAsz+Hgo4hkel6W+O39o/lR0EtjohCUlfG92DTgyoUxGXc2g88LyT83 G4Gob2UBoqiWnsHpYjWFP6/HlAcr6nUXa6CGJqkyhzud6+c9ZsdfOIhDpZfyxh2x ZzH/D5f8D7M= =aI0k -----END PGP SIGNATURE----- From python-checkins at python.org Mon Apr 16 19:08:52 2007 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 16 Apr 2007 19:08:52 +0200 (CEST) Subject: [Python-checkins] r54843 - peps/trunk/pep-0306.txt Message-ID: <20070416170852.3BD271E4006@bag.python.org> Author: guido.van.rossum Date: Mon Apr 16 19:08:51 2007 New Revision: 54843 Modified: peps/trunk/pep-0306.txt Log: Add explanation / instructions for required 2nd Python-ast.c submit. Modified: peps/trunk/pep-0306.txt ============================================================================== --- peps/trunk/pep-0306.txt (original) +++ peps/trunk/pep-0306.txt Mon Apr 16 19:08:51 2007 @@ -71,6 +71,13 @@ __ Documentation must be written! + __ After everything's been checked in, you're likely to see a new + change to Python/Python-ast.c. This is because this + (generated) file contains the SVN version of the source from + which it was generated. There's no way to avoid this; you just + have to submit this file separately. + + References [1] SF Bug #676521, parser module validation failure From python-checkins at python.org Tue Apr 17 00:10:32 2007 From: python-checkins at python.org (collin.winter) Date: Tue, 17 Apr 2007 00:10:32 +0200 (CEST) Subject: [Python-checkins] r54844 - python/trunk/Lib/test/test_normalization.py Message-ID: <20070416221032.C39F81E400E@bag.python.org> Author: collin.winter Date: Tue Apr 17 00:10:32 2007 New Revision: 54844 Modified: python/trunk/Lib/test/test_normalization.py Log: Check the availability of the urlfetch resource earlier than before. Modified: python/trunk/Lib/test/test_normalization.py ============================================================================== --- python/trunk/Lib/test/test_normalization.py (original) +++ python/trunk/Lib/test/test_normalization.py Tue Apr 17 00:10:32 2007 @@ -88,6 +88,8 @@ def test_main(): + # Hit the exception early + open_urlresource(TESTDATAURL) run_unittest(NormalizationTest) if __name__ == "__main__": From python-checkins at python.org Tue Apr 17 05:51:16 2007 From: python-checkins at python.org (brett.cannon) Date: Tue, 17 Apr 2007 05:51:16 +0200 (CEST) Subject: [Python-checkins] r54847 - in sandbox/trunk/pep0: TODO pep0/parse.py pep0/pep.py test_pep0.py Message-ID: <20070417035116.3546C1E400F@bag.python.org> Author: brett.cannon Date: Tue Apr 17 05:51:06 2007 New Revision: 54847 Modified: sandbox/trunk/pep0/TODO sandbox/trunk/pep0/pep0/parse.py sandbox/trunk/pep0/pep0/pep.py sandbox/trunk/pep0/test_pep0.py Log: Rework pep0.parse (including some renaming). Also write tests for split_metadata. This makes test_pep0 only run tests that actually work. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Tue Apr 17 05:51:06 2007 @@ -1,6 +1,9 @@ +* Update test_pep0: + + Group tests for pep0.parse together. + + Update tests to match current functionality. + * Handle XXX comments: + __init__ - + parse + pep + output + Update test_pep0 to reflect refactoring. Modified: sandbox/trunk/pep0/pep0/parse.py ============================================================================== --- sandbox/trunk/pep0/pep0/parse.py (original) +++ sandbox/trunk/pep0/pep0/parse.py Tue Apr 17 05:51:06 2007 @@ -8,22 +8,20 @@ + Must be an integer. + Must match file name. -XXX - * Remove metadata validation and move to pep class. - + Still validate PEP number is an integer (it's needed for error - reporting from this point forward). - + Validate PEP number matches number in file name. - """ from __future__ import with_statement from .pep import PEP import os -import re -def consume_headers(directory='.'): +def consume_directory(directory): """Pull out metadata for every PEP in the specified directory and return - them in a list sorted by PEP name.""" + them in a list sorted by PEP name. + + The PEP file name must start with 'pep-' and end with '.txt' to be + considered. + + """ peps = [] for file_name in os.listdir(directory): if file_name.startswith('pep-') and file_name.endswith('.txt'): @@ -33,96 +31,54 @@ def consume_pep(path): """Consume the specified file as a PEP to get its metadata.""" - pep_info = {} + metadata = {} with open(path, 'rU') as pep_file: try: for line in pep_file: if line == '\n': + # Found end of metadata. break - elif line[1].isspace(): - type_ = parse_metadata(pep_info, line, type_) + elif line[0].isspace(): + # Whitespace indent signifies multi-line field data. + field, data = split_metadata(line, field) else: - type_ = parse_metadata(pep_info, line) + field, data = split_metadata(line) + prev_data = metadata.get(field) + if prev_data: + data = metadata[field] + data + metadata[field] = data except Exception: print "*** In", pep_file raise - if not 'PEP' in pep_info: + # Make sure PEP field was found ... + if not 'PEP' in metadata: raise ValueError("PEP at file %s lacks a PEP number" % path) - if not 'Author' in pep_info: - raise ValueError("PEP %s is missing the Author field" % - pep_info['PEP']) - if len(pep_info['Author']) < 1: - raise ValueError("PEP %s is lacking authors" % pep_info['PEP']) - if pep_info['Type'] not in PEP.type_values: - raise ValueError("%s is an invalid Type value for PEP %s" % - (pep_info['Type'], pep_info['PEP'])) - if pep_info['Status'] not in PEP.status_values: - raise ValueError("%s is an invalid Status value for PEP %s" % - (pep_info['Status'], pep_info['PEP'])) - return pep_info - -def parse_metadata(pep_info, line, previous_type=None): - """Parse the given line for PEP metadata, adding on to existing metadata if - previous_type is specified, returning the last type of metadata handled.""" - if previous_type: - type_ = previous_type + # ... it matches the file name in some way ... + if metadata['PEP'] not in path: + raise ValueError("PEP number in file %s does not match number " + "specified in its file name" % path) + # ... and that the number is a valid integer. + try: + metadata['PEP'] = int(metadata['PEP']) + except ValueError: + raise ValueError("PEP number in file %s is not valid" % path) + return metadata + +def split_metadata(line, continue_field=None): + """Parse the given line for PEP metadata, returning the field and data for + the line parsed. + + If continue_field is specified then return that as the field parsed. + + """ + if continue_field: + field = continue_field data = line else: - type_, data = line.split(':', 1) - type_ = type_.strip() + try: + field, data = line.split(':', 1) + except ValueError: + raise ValueError("could not find field in %r" % line) + field = field.strip() data = data.strip() - handler = handlers.get(type_, handle_generic) - result = handler(data) - if previous_type: - previous_data = pep_info[type_] - if not isinstance(previous_data, list): - previous_data = [previous_data] - pep_info[type_] = previous_data - previous_data.extend(result) - else: - pep_info[type_] = result - return type_ - -def handle_generic(data): - """Default handler for PEP metadata.""" - return data - -def handle_pep_num(data): - """Return the integer for the PEP number.""" - return int(data) - -def handle_author(data): - """Return a list of author names.""" - angled = r'(?P.+?) <.+?>' - paren = r'.+? \((?P.+?)\)' - simple = r'(?P[^,]+)' - author_list = [] - for regex in (angled, paren, simple): - # Watch out for commas separating multiple names. - regex += '(,\s+)?' - for match in re.finditer(regex, data): - author = match.group('author') - # Watch out for suffixes like 'Jr.' when they are comma-separated - # from the name and thus cause issues when *all* names are only - # separated by commas. - author = match.group('author') - if not author.partition(' ')[1] and author.endswith('.'): - prev_author = author_list.pop() - author = ', '.join([prev_author, author]) - author_list.append(author) - else: - # If authors were found then stop searching as only expect one - # style of author citation. - if author_list: - break - return author_list - -def handle_csv(data): - """Handle the Post-History.""" - return [value.strip() for value in data.split(',') if value] - -handlers = {'Author': handle_author, - 'PEP': handle_pep_num, - 'Post-History': handle_csv, - } - + return field, data Modified: sandbox/trunk/pep0/pep0/pep.py ============================================================================== --- sandbox/trunk/pep0/pep0/pep.py (original) +++ sandbox/trunk/pep0/pep0/pep.py Tue Apr 17 05:51:06 2007 @@ -80,4 +80,30 @@ finished.append(pep) return meta, info, accepted, open_, finished, empty, dead +def handle_author(data): + """Return a list of author names.""" + angled = r'(?P.+?) <.+?>' + paren = r'.+? \((?P.+?)\)' + simple = r'(?P[^,]+)' + author_list = [] + for regex in (angled, paren, simple): + # Watch out for commas separating multiple names. + regex += '(,\s+)?' + for match in re.finditer(regex, data): + author = match.group('author') + # Watch out for suffixes like 'Jr.' when they are comma-separated + # from the name and thus cause issues when *all* names are only + # separated by commas. + author = match.group('author') + if not author.partition(' ')[1] and author.endswith('.'): + prev_author = author_list.pop() + author = ', '.join([prev_author, author]) + author_list.append(author) + else: + # If authors were found then stop searching as only expect one + # style of author citation. + if author_list: + break + return author_list + Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Tue Apr 17 05:51:06 2007 @@ -1,11 +1,38 @@ from __future__ import with_statement -import pep0 +import pep0.parse import unittest from test import test_support from contextlib import contextmanager import os +class ParseTests(unittest.TestCase): + + """Test pep0.parse .""" + + def test_split_metadata_single_line(self): + # Test basic use case. + gave_field = "field" + gave_data = "data" + # Spaces in separator help test whitespace stripping. + for sep in (':', ' :', ': '): + line = sep.join([gave_field, gave_data]) + got_field, got_data = pep0.parse.split_metadata(line) + self.failUnlessEqual(gave_field, got_field) + self.failUnlessEqual(gave_data, got_data) + bad_line = 'abc' + self.failUnlessRaises(ValueError, pep0.parse.split_metadata, bad_line) + + def test_split_metadata_continuing_line(self): + # Make sure that if the line is considered a continuation of another + # one that the same field is returned. + gave_field ='a' + gave_data = 'b:c' + got_field, got_data = pep0.parse.split_metadata(gave_data, gave_field) + self.failUnlessEqual(got_field, gave_field) + self.failUnlessEqual(got_data, gave_data) + + class HandlerTests(unittest.TestCase): """Test the PEP field handlers for parsing data.""" @@ -263,11 +290,7 @@ def test_main(): test_support.run_unittest( - HandlerTests, - ParseMetaDataTests, - PEPClassTests, - ConsumePepTests, - EntryOutputTests, + ParseTests, ) From python-checkins at python.org Tue Apr 17 05:55:57 2007 From: python-checkins at python.org (brett.cannon) Date: Tue, 17 Apr 2007 05:55:57 +0200 (CEST) Subject: [Python-checkins] r54848 - sandbox/trunk/pep0/pep0/__init__.py Message-ID: <20070417035557.984E51E400C@bag.python.org> Author: brett.cannon Date: Tue Apr 17 05:55:48 2007 New Revision: 54848 Modified: sandbox/trunk/pep0/pep0/__init__.py Log: Fix bug from renaming in pep0.parse . Modified: sandbox/trunk/pep0/pep0/__init__.py ============================================================================== --- sandbox/trunk/pep0/pep0/__init__.py (original) +++ sandbox/trunk/pep0/pep0/__init__.py Tue Apr 17 05:55:48 2007 @@ -16,7 +16,7 @@ from __future__ import absolute_import if __name__ == '__main__': - from pep0.parse import consume_headers, consume_pep + from pep0.parse import consume_directory, consume_pep from pep0.pep import sort_peps, PEP from pep0.output import write_column_headers, write_pep from pep0.statictext import header, intro, references, footer @@ -29,7 +29,7 @@ else: path = argv[1] if os.path.isdir(path): - peps = consume_headers(path) + peps = consume_directory(path) else: peps = [consume_pep(path)] From python-checkins at python.org Tue Apr 17 07:02:06 2007 From: python-checkins at python.org (martin.v.loewis) Date: Tue, 17 Apr 2007 07:02:06 +0200 (CEST) Subject: [Python-checkins] r54849 - python/trunk/Misc/developers.txt Message-ID: <20070417050206.6FB7E1E400C@bag.python.org> Author: martin.v.loewis Date: Tue Apr 17 07:02:01 2007 New Revision: 54849 Modified: python/trunk/Misc/developers.txt Log: Add Travis Oliphant. Modified: python/trunk/Misc/developers.txt ============================================================================== --- python/trunk/Misc/developers.txt (original) +++ python/trunk/Misc/developers.txt Tue Apr 17 07:02:01 2007 @@ -17,7 +17,10 @@ Permissions History ------------------- -- Ziga Seilnacht was given SVN occess on 09 Mar 2007 by MvL, +- Travis Oliphant was given SVN access on 17 Apr 2007 by MvL, + for implementing the extended buffer protocol. + +- Ziga Seilnacht was given SVN access on 09 Mar 2007 by MvL, for general maintenance. - Pete Shinners was given SVN access on 04 Mar 2007 by NCN, From buildbot at python.org Tue Apr 17 17:38:48 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 17 Apr 2007 15:38:48 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP-2 trunk Message-ID: <20070417153848.BDF851E400D@bag.python.org> The Buildbot has detected a new failure of x86 XP-2 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP-2%2520trunk/builds/1 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_socket_ssl sincerely, -The Buildbot From python-checkins at python.org Wed Apr 18 04:02:21 2007 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 18 Apr 2007 04:02:21 +0200 (CEST) Subject: [Python-checkins] r54857 - in python/branches/release25-maint: Misc/NEWS Objects/setobject.c Message-ID: <20070418020221.1AD0F1E400D@bag.python.org> Author: raymond.hettinger Date: Wed Apr 18 04:02:15 2007 New Revision: 54857 Modified: python/branches/release25-maint/Misc/NEWS python/branches/release25-maint/Objects/setobject.c Log: Revert 53667 Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Wed Apr 18 04:02:15 2007 @@ -14,6 +14,7 @@ - Revert SF #1615701: dict.update() does *not* call __getitem__() or keys() if subclassed. This is to remain consistent with 2.5. + Also revert revision 53667 with made a similar change to set.update(). What's New in Python 2.5.1c1? Modified: python/branches/release25-maint/Objects/setobject.c ============================================================================== --- python/branches/release25-maint/Objects/setobject.c (original) +++ python/branches/release25-maint/Objects/setobject.c Wed Apr 18 04:02:15 2007 @@ -912,7 +912,7 @@ { PyObject *key, *it; - if (PyAnySet_CheckExact(other)) + if (PyAnySet_Check(other)) return set_merge(so, other); if (PyDict_CheckExact(other)) { @@ -1207,7 +1207,7 @@ if (result == NULL) return NULL; - if (PyAnySet_CheckExact(other)) { + if (PyAnySet_Check(other)) { Py_ssize_t pos = 0; setentry *entry; @@ -1331,7 +1331,7 @@ if ((PyObject *)so == other) return set_clear_internal(so); - if (PyAnySet_CheckExact(other)) { + if (PyAnySet_Check(other)) { setentry *entry; Py_ssize_t pos = 0; @@ -1380,7 +1380,7 @@ setentry *entry; Py_ssize_t pos = 0; - if (!PyAnySet_CheckExact(other) && !PyDict_CheckExact(other)) { + if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) { result = set_copy(so); if (result == NULL) return NULL; @@ -1487,7 +1487,7 @@ Py_RETURN_NONE; } - if (PyAnySet_CheckExact(other)) { + if (PyAnySet_Check(other)) { Py_INCREF(other); otherset = (PySetObject *)other; } else { @@ -1570,7 +1570,7 @@ setentry *entry; Py_ssize_t pos = 0; - if (!PyAnySet_CheckExact(other)) { + if (!PyAnySet_Check(other)) { PyObject *tmp, *result; tmp = make_new_set(&PySet_Type, other); if (tmp == NULL) @@ -1599,7 +1599,7 @@ { PyObject *tmp, *result; - if (!PyAnySet_CheckExact(other)) { + if (!PyAnySet_Check(other)) { tmp = make_new_set(&PySet_Type, other); if (tmp == NULL) return NULL; From buildbot at python.org Wed Apr 18 04:11:59 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Apr 2007 02:11:59 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP 2.5 Message-ID: <20070418021159.829691E400D@bag.python.org> The Buildbot has detected a new failure of x86 XP 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%25202.5/builds/200 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: raymond.hettinger Build had warnings: warnings failed slave lost sincerely, -The Buildbot From python-checkins at python.org Wed Apr 18 04:37:26 2007 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2007 04:37:26 +0200 (CEST) Subject: [Python-checkins] r54858 - sandbox/trunk/pep0/TODO sandbox/trunk/pep0/test_pep0.py Message-ID: <20070418023726.4DBF51E400D@bag.python.org> Author: brett.cannon Date: Wed Apr 18 04:37:19 2007 New Revision: 54858 Modified: sandbox/trunk/pep0/TODO sandbox/trunk/pep0/test_pep0.py Log: Add tests for pep0.parse.consume_pep. Modified: sandbox/trunk/pep0/TODO ============================================================================== --- sandbox/trunk/pep0/TODO (original) +++ sandbox/trunk/pep0/TODO Wed Apr 18 04:37:19 2007 @@ -1,12 +1,9 @@ * Update test_pep0: - + Group tests for pep0.parse together. - + Update tests to match current functionality. - -* Handle XXX comments: - + __init__ - + pep + + authors + output - + Update test_pep0 to reflect refactoring. + + pep + + statictext + Functionality to add -------------------- Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Wed Apr 18 04:37:19 2007 @@ -10,6 +10,20 @@ """Test pep0.parse .""" + def setUp(self): + self.num = 42 + self.path = test_support.TESTFN + str(self.num) + + def tearDown(self): + if os.path.exists(self.path): + os.unlink(self.path) + + def create_simple_pep(self, num=None): + if num is None: + num = self.num + with open(self.path, 'w') as pep_file: + pep_file.write("PEP: %s\n\nBody" % num) + def test_split_metadata_single_line(self): # Test basic use case. gave_field = "field" @@ -32,6 +46,27 @@ self.failUnlessEqual(got_field, gave_field) self.failUnlessEqual(got_data, gave_data) + def test_consume_pep_number_field(self): + # All PEPs must have a PEP field. + self.create_simple_pep() + metadata = pep0.parse.consume_pep(self.path) + self.failUnless('PEP' in metadata) + self.failUnlessEqual(metadata['PEP'], self.num) + + def test_consume_pep_file_name(self): + # The PEP number is expected to be in file name. + # Testing positive results implicit in other tests of pep0.consume_pep. + self.path = test_support.TESTFN + assert str(self.num) not in self.path + self.create_simple_pep() + self.failUnlessRaises(ValueError, pep0.parse.consume_pep, self.path) + + def test_consume_pep_valid_int(self): + # The found value of the 'PEP' field is expected to be a valid number. + self.create_simple_pep("XXX") + self.failUnlessRaises(ValueError, pep0.parse.consume_pep, self.path) + + class HandlerTests(unittest.TestCase): From python-checkins at python.org Wed Apr 18 05:01:48 2007 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2007 05:01:48 +0200 (CEST) Subject: [Python-checkins] r54859 - sandbox/trunk/pep0/test_pep0.py Message-ID: <20070418030148.BF0931E400D@bag.python.org> Author: brett.cannon Date: Wed Apr 18 05:01:41 2007 New Revision: 54859 Modified: sandbox/trunk/pep0/test_pep0.py Log: A wee bit of refactoring. Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Wed Apr 18 05:01:41 2007 @@ -1,6 +1,7 @@ from __future__ import with_statement import pep0.parse +import itertools import unittest from test import test_support from contextlib import contextmanager @@ -10,9 +11,12 @@ """Test pep0.parse .""" + def create_path(self): + return test_support.TESTFN + str(self.num) + def setUp(self): self.num = 42 - self.path = test_support.TESTFN + str(self.num) + self.path = self.create_path() def tearDown(self): if os.path.exists(self.path): @@ -67,7 +71,6 @@ self.failUnlessRaises(ValueError, pep0.parse.consume_pep, self.path) - class HandlerTests(unittest.TestCase): """Test the PEP field handlers for parsing data.""" From python-checkins at python.org Wed Apr 18 05:02:17 2007 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2007 05:02:17 +0200 (CEST) Subject: [Python-checkins] r54860 - sandbox/trunk/pep0/pep0/parse.py Message-ID: <20070418030217.D85CF1E400D@bag.python.org> Author: brett.cannon Date: Wed Apr 18 05:02:13 2007 New Revision: 54860 Modified: sandbox/trunk/pep0/pep0/parse.py Log: Add an assert to catch PEPs that are malformed. Modified: sandbox/trunk/pep0/pep0/parse.py ============================================================================== --- sandbox/trunk/pep0/pep0/parse.py (original) +++ sandbox/trunk/pep0/pep0/parse.py Wed Apr 18 05:02:13 2007 @@ -32,6 +32,7 @@ def consume_pep(path): """Consume the specified file as a PEP to get its metadata.""" metadata = {} + field = None with open(path, 'rU') as pep_file: try: for line in pep_file: @@ -39,6 +40,7 @@ # Found end of metadata. break elif line[0].isspace(): + assert field is not None # Whitespace indent signifies multi-line field data. field, data = split_metadata(line, field) else: From python-checkins at python.org Wed Apr 18 05:14:00 2007 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2007 05:14:00 +0200 (CEST) Subject: [Python-checkins] r54861 - sandbox/trunk/pep0/test_pep0.py Message-ID: <20070418031400.AEF281E400D@bag.python.org> Author: brett.cannon Date: Wed Apr 18 05:13:56 2007 New Revision: 54861 Modified: sandbox/trunk/pep0/test_pep0.py Log: Test multi-line data values. Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Wed Apr 18 05:13:56 2007 @@ -70,6 +70,19 @@ self.create_simple_pep("XXX") self.failUnlessRaises(ValueError, pep0.parse.consume_pep, self.path) + def test_consume_pep_multiline_data(self): + # If data spans multiple lines it should come out as a single one after + # parsing. + line1 = "a, b, c," + line2 = "d, e, f" + with open(self.path, 'w') as pep_file: + pep_file.write("PEP: %s\n" % self.num) + pep_file.write("multiline: a, b, c,\n") + pep_file.write(" d, e, f\n") + pep_file.write("\nBody") + metadata = pep0.parse.consume_pep(self.path) + self.failUnlessEqual(metadata['multiline'], line1 + line2) + class HandlerTests(unittest.TestCase): From python-checkins at python.org Wed Apr 18 05:14:54 2007 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2007 05:14:54 +0200 (CEST) Subject: [Python-checkins] r54862 - sandbox/trunk/pep0/test_pep0.py Message-ID: <20070418031454.05A421E400D@bag.python.org> Author: brett.cannon Date: Wed Apr 18 05:14:51 2007 New Revision: 54862 Modified: sandbox/trunk/pep0/test_pep0.py Log: Remove old test code for parsing PEP metadata. Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Wed Apr 18 05:14:51 2007 @@ -132,44 +132,6 @@ self.failUnlessEqual(got, expect) -class ParseMetaDataTests(unittest.TestCase): - - """Test the parsing of the headers of PEPs.""" - - def test_parse_known_formats(self): - # Handle specific metadata format types. - assert "PEP" in pep0.handlers - line = "PEP: 42" - info = {} - handled = pep0.parse_metadata(info, line) - self.failUnlessEqual(handled, "PEP") - self.failUnless("PEP" in info) - self.failUnlessEqual(info['PEP'], 42) - - def test_parse_unknown_formats(self): - # If a format is not known then it should just be returned with - # whitespace stripped. - info = {} - type_ = "Spam" - data = "Monty Python" - line = "%s: %s" % (type_, data) - handled = pep0.parse_metadata(info, line) - self.failUnlessEqual(handled, type_) - self.failUnless(type_ in info) - self.failUnlessEqual(info[type_], data) - - def test_multiline_formats(self): - # Deal with formats that can span multiple lines (e.g., authors and - # Post-History). - type_ = 'Prev' - info = {type_ : [1]} - data = 'A' - handled = pep0.parse_metadata(info, data, type_) - self.failUnlessEqual(handled, type_) - self.failUnlessEqual(len(info[type_]), 2) - self.failUnlessEqual(info[type_][1], data) - - class PEPClassTests(unittest.TestCase): """Test the PEP class.""" From python-checkins at python.org Wed Apr 18 05:35:58 2007 From: python-checkins at python.org (anthony.baxter) Date: Wed, 18 Apr 2007 05:35:58 +0200 (CEST) Subject: [Python-checkins] r54863 - in python/branches/release25-maint: Doc/commontex/boilerplate.tex Include/patchlevel.h Lib/idlelib/NEWS.txt Lib/idlelib/idlever.py Misc/NEWS Message-ID: <20070418033558.C2C451E400D@bag.python.org> Author: anthony.baxter Date: Wed Apr 18 05:35:45 2007 New Revision: 54863 Modified: python/branches/release25-maint/Doc/commontex/boilerplate.tex python/branches/release25-maint/Include/patchlevel.h python/branches/release25-maint/Lib/idlelib/NEWS.txt python/branches/release25-maint/Lib/idlelib/idlever.py python/branches/release25-maint/Misc/NEWS Log: 2.5.1 final Modified: python/branches/release25-maint/Doc/commontex/boilerplate.tex ============================================================================== --- python/branches/release25-maint/Doc/commontex/boilerplate.tex (original) +++ python/branches/release25-maint/Doc/commontex/boilerplate.tex Wed Apr 18 05:35:45 2007 @@ -5,5 +5,5 @@ Email: \email{docs at python.org} } -\date{5th April, 2007} % XXX update before final release! +\date{18th April, 2007} % XXX update before final release! \input{patchlevel} % include Python version information Modified: python/branches/release25-maint/Include/patchlevel.h ============================================================================== --- python/branches/release25-maint/Include/patchlevel.h (original) +++ python/branches/release25-maint/Include/patchlevel.h Wed Apr 18 05:35:45 2007 @@ -22,11 +22,11 @@ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 1 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.5.1c1" +#define PY_VERSION "2.5.1" /* Subversion Revision number of this file (not of the repository) */ #define PY_PATCHLEVEL_REVISION "$Revision$" Modified: python/branches/release25-maint/Lib/idlelib/NEWS.txt ============================================================================== --- python/branches/release25-maint/Lib/idlelib/NEWS.txt (original) +++ python/branches/release25-maint/Lib/idlelib/NEWS.txt Wed Apr 18 05:35:45 2007 @@ -1,3 +1,8 @@ +What's New in IDLE 1.2.1? +========================= + +*Release date: 18-APR-2007* + What's New in IDLE 1.2.1c1? =========================== Modified: python/branches/release25-maint/Lib/idlelib/idlever.py ============================================================================== --- python/branches/release25-maint/Lib/idlelib/idlever.py (original) +++ python/branches/release25-maint/Lib/idlelib/idlever.py Wed Apr 18 05:35:45 2007 @@ -1 +1 @@ -IDLE_VERSION = "1.2.1c1" +IDLE_VERSION = "1.2.1" Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Wed Apr 18 05:35:45 2007 @@ -7,7 +7,7 @@ What's New in Python 2.5.1? ============================= -*Release date: XX-APR-2007* +*Release date: 18-APR-2007* Core and builtins ----------------- From python-checkins at python.org Wed Apr 18 05:53:22 2007 From: python-checkins at python.org (anthony.baxter) Date: Wed, 18 Apr 2007 05:53:22 +0200 (CEST) Subject: [Python-checkins] r54864 - python/tags/r251 Message-ID: <20070418035322.674D01E400D@bag.python.org> Author: anthony.baxter Date: Wed Apr 18 05:53:15 2007 New Revision: 54864 Added: python/tags/r251/ - copied from r54863, python/branches/release25-maint/ Log: Tagging for release of Python 2.5.1 From python-checkins at python.org Wed Apr 18 06:07:00 2007 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2007 06:07:00 +0200 (CEST) Subject: [Python-checkins] r54865 - in sandbox/trunk/pep0: pep0/pep.py test_pep0.py Message-ID: <20070418040700.921851E400D@bag.python.org> Author: brett.cannon Date: Wed Apr 18 06:06:52 2007 New Revision: 54865 Modified: sandbox/trunk/pep0/pep0/pep.py sandbox/trunk/pep0/test_pep0.py Log: Beginnings of a PEP class. Testing of __init__ is not complete, but initial coding of the method is done. Modified: sandbox/trunk/pep0/pep0/pep.py ============================================================================== --- sandbox/trunk/pep0/pep0/pep.py (original) +++ sandbox/trunk/pep0/pep0/pep.py Wed Apr 18 06:06:52 2007 @@ -4,6 +4,7 @@ * Flesh out PEP class. """ +import re class PEP(object): @@ -15,12 +16,75 @@ "Active", "Draft") def __init__(self, metadata_dict): - """Init object based on dict containing metadata from a file.""" - pass + """Init object based on dict containing metadata from a file. + + Required keys are: + + * PEP + value must be an integer. + + * Type + Value must match a value in self.type_values. + + * Status + Value must match a value in self.status_values. + + * Author + Value must have at least one author in the string as returned + by self.parse_author. + + """ + # Verify keys exist. + for required_key in ('PEP', 'Type', 'Status', 'Author'): + if required_key not in metadata_dict: + raise KeyError("required key %r not in dict") + # 'PEP'. PEP parsing should have already converted the number to an + # integer, so just being safe here. + self.number = int(metadata_dict['PEP']) + # 'Type'. + type_ = metadata_dict['Type'] + if type_ not in self.type_values: + raise ValueError('%r is not a valid Type value (PEP %s)' % + (type_, self.number)) + self.type_ = type_ + # 'Status'. + status = metadata_dict['Status'] + if status not in self.status_values: + raise ValueError("%r is not a valid Status value (PEP %s)" % + (status, self.number)) + self.status = status + # 'Author'. + authors = self._parse_author(metadata_dict['Author']) + if len(authors) < 1: + raise ValueError("no authors found (PEP %s)" % self.number) + self.authors = authors + + def _parse_author(self, data): + """Return a list of author names.""" + angled = r'(?P.+?) <.+?>' + paren = r'.+? \((?P.+?)\)' + simple = r'(?P[^,]+)' + author_list = [] + for regex in (angled, paren, simple): + # Watch out for commas separating multiple names. + regex += '(,\s*)?' + for match in re.finditer(regex, data): + author = match.group('author') + # Watch out for suffixes like 'Jr.' when they are comma-separated + # from the name and thus cause issues when *all* names are only + # separated by commas. + author = match.group('author') + if not author.partition(' ')[1] and author.endswith('.'): + prev_author = author_list.pop() + author = ', '.join([prev_author, author]) + author_list.append(author) + else: + # If authors were found then stop searching as only expect one + # style of author citation. + if author_list: + break + return author_list - def validate(self): - """Validate that the instance data.""" - pass def __str__(self): """Return the line entry for the PEP.""" @@ -80,30 +144,5 @@ finished.append(pep) return meta, info, accepted, open_, finished, empty, dead -def handle_author(data): - """Return a list of author names.""" - angled = r'(?P.+?) <.+?>' - paren = r'.+? \((?P.+?)\)' - simple = r'(?P[^,]+)' - author_list = [] - for regex in (angled, paren, simple): - # Watch out for commas separating multiple names. - regex += '(,\s+)?' - for match in re.finditer(regex, data): - author = match.group('author') - # Watch out for suffixes like 'Jr.' when they are comma-separated - # from the name and thus cause issues when *all* names are only - # separated by commas. - author = match.group('author') - if not author.partition(' ')[1] and author.endswith('.'): - prev_author = author_list.pop() - author = ', '.join([prev_author, author]) - author_list.append(author) - else: - # If authors were found then stop searching as only expect one - # style of author citation. - if author_list: - break - return author_list Modified: sandbox/trunk/pep0/test_pep0.py ============================================================================== --- sandbox/trunk/pep0/test_pep0.py (original) +++ sandbox/trunk/pep0/test_pep0.py Wed Apr 18 06:06:52 2007 @@ -136,29 +136,30 @@ """Test the PEP class.""" - def test_valid_init(self): - # Make sure that a PEP instance can be created from a dict with valid - # entries. - pass - - # Number cannot be invalid as that is checked during parsing of the PEP. + def setUp(self): + self.metadata = {'PEP': 42, 'Type': pep0.pep.PEP.type_values[0], + 'Status': pep0.pep.PEP.status_values[0], + 'Author': "Brett Cannon"} + + def test_init_number(self): + # PEP number must be an int. + pep = pep0.pep.PEP(self.metadata) + self.failUnlessEqual(pep.number, self.metadata['PEP']) + self.metadata['PEP'] = 'XXX' + self.failUnlessRaises(ValueError, pep0.pep.PEP, self.metadata) - def test_invalid_status(self): + def test_init_status(self): # Invalid Status entry raises an exception. pass - def test_invalid_type(self): + def test_init_type(self): # Invalid type should raise an exception. pass - def test_invalid_authors(self): + def test_init_authors(self): # There should be at least one author. pass - def test_str(self): - # String representation of the PEP. - pass - @contextmanager def test_file(path): @@ -304,6 +305,7 @@ def test_main(): test_support.run_unittest( ParseTests, + PEPClassTests, ) From nnorwitz at gmail.com Wed Apr 18 06:20:07 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Wed, 18 Apr 2007 00:20:07 -0400 Subject: [Python-checkins] Python Regression Test Failures doc (1) Message-ID: <20070418042007.GA7991@python.psfb.org> TEXINPUTS=/home/neal/python/r25/Doc/commontex: python /home/neal/python/r25/Doc/tools/mkhowto --html --about html/stdabout.dat --iconserver ../icons --favicon ../icons/pyfav.png --address "See About this document... for information on suggesting changes." --up-link ../index.html --up-title "Python Documentation Index" --global-module-index "../modindex.html" --dvips-safe --dir html/api api/api.tex *** Session transcript and error messages are in /home/neal/python/r25/Doc/html/api/api.how. *** Exited with status 1. The relevant lines from the transcript are: ------------------------------------------------------------------------ +++ latex api This is TeX, Version 3.14159 (Web2C 7.4.5) (/home/neal/python/r25/Doc/api/api.tex LaTeX2e <2001/06/01> Babel and hyphenation patterns for american, french, german, ngerman, n ohyphenation, loaded. (/home/neal/python/r25/Doc/texinputs/manual.cls Document Class: manual 1998/03/03 Document class (Python manual) (/home/neal/python/r25/Doc/texinputs/pypaper.sty (/usr/share/texmf/tex/latex/psnfss/times.sty) Using Times instead of Computer Modern. ) (/usr/share/texmf/tex/latex/misc/fancybox.sty Style option: `fancybox' v1.3 <2000/09/19> (tvz) ) (/usr/share/texmf/tex/latex/base/report.cls Document Class: report 2001/04/21 v1.4e Standard LaTeX document class (/usr/share/texmf/tex/latex/base/size10.clo)) (/home/neal/python/r25/Doc/texinputs/fancyhdr.sty) Using fancier footers than usual. (/home/neal/python/r25/Doc/texinputs/fncychap.sty) Using fancy chapter headings. (/home/neal/python/r25/Doc/texinputs/python.sty (/usr/share/texmf/tex/latex/tools/longtable.sty) (/home/neal/python/r25/Doc/texinputs/underscore.sty) (/usr/share/texmf/tex/latex/tools/verbatim.sty) (/usr/share/texmf/tex/latex/base/alltt.sty))) (/home/neal/python/r25/Doc/commontex/boilerplate.tex ! LaTeX Error: Missing \begin{document}. See the LaTeX manual or LaTeX Companion for explanation. Type H for immediate help. ... l.8 < <<<<<< .mine ? ! Emergency stop. ... l.8 < <<<<<< .mine No pages of output. Transcript written on api.log. *** Session transcript and error messages are in /home/neal/python/r25/Doc/html/api/api.how. *** Exited with status 1. +++ TEXINPUTS=/home/neal/python/r25/Doc/api:/home/neal/python/r25/Doc/commontex:/home/neal/python/r25/Doc/paper-letter:/home/neal/python/r25/Doc/texinputs: +++ latex api make: *** [html/api/api.html] Error 1 From nnorwitz at gmail.com Wed Apr 18 07:20:04 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Wed, 18 Apr 2007 01:20:04 -0400 Subject: [Python-checkins] Python Regression Test Failures doc (1) Message-ID: <20070418052004.GA8337@python.psfb.org> TEXINPUTS=/home/neal/python/r25/Doc/commontex: python /home/neal/python/r25/Doc/tools/mkhowto --html --about html/stdabout.dat --iconserver ../icons --favicon ../icons/pyfav.png --address "See About this document... for information on suggesting changes." --up-link ../index.html --up-title "Python Documentation Index" --global-module-index "../modindex.html" --dvips-safe --dir html/api api/api.tex *** Session transcript and error messages are in /home/neal/python/r25/Doc/html/api/api.how. *** Exited with status 1. The relevant lines from the transcript are: ------------------------------------------------------------------------ +++ latex api This is TeX, Version 3.14159 (Web2C 7.4.5) (/home/neal/python/r25/Doc/api/api.tex LaTeX2e <2001/06/01> Babel and hyphenation patterns for american, french, german, ngerman, n ohyphenation, loaded. (/home/neal/python/r25/Doc/texinputs/manual.cls Document Class: manual 1998/03/03 Document class (Python manual) (/home/neal/python/r25/Doc/texinputs/pypaper.sty (/usr/share/texmf/tex/latex/psnfss/times.sty) Using Times instead of Computer Modern. ) (/usr/share/texmf/tex/latex/misc/fancybox.sty Style option: `fancybox' v1.3 <2000/09/19> (tvz) ) (/usr/share/texmf/tex/latex/base/report.cls Document Class: report 2001/04/21 v1.4e Standard LaTeX document class (/usr/share/texmf/tex/latex/base/size10.clo)) (/home/neal/python/r25/Doc/texinputs/fancyhdr.sty) Using fancier footers than usual. (/home/neal/python/r25/Doc/texinputs/fncychap.sty) Using fancy chapter headings. (/home/neal/python/r25/Doc/texinputs/python.sty (/usr/share/texmf/tex/latex/tools/longtable.sty) (/home/neal/python/r25/Doc/texinputs/underscore.sty) (/usr/share/texmf/tex/latex/tools/verbatim.sty) (/usr/share/texmf/tex/latex/base/alltt.sty))) (/home/neal/python/r25/Doc/commontex/boilerplate.tex ! LaTeX Error: Missing \begin{document}. See the LaTeX manual or LaTeX Companion for explanation. Type H for immediate help. ... l.8 < <<<<<< .mine ? ! Emergency stop. ... l.8 < <<<<<< .mine No pages of output. Transcript written on api.log. *** Session transcript and error messages are in /home/neal/python/r25/Doc/html/api/api.how. *** Exited with status 1. +++ TEXINPUTS=/home/neal/python/r25/Doc/api:/home/neal/python/r25/Doc/commontex:/home/neal/python/r25/Doc/paper-letter:/home/neal/python/r25/Doc/texinputs: +++ latex api make: *** [html/api/api.html] Error 1 From python-checkins at python.org Wed Apr 18 07:42:05 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 18 Apr 2007 07:42:05 +0200 (CEST) Subject: [Python-checkins] r54866 - in sandbox/trunk/2to3: HACKING fixes/fix_dummy.py Message-ID: <20070418054205.048251E400D@bag.python.org> Author: collin.winter Date: Wed Apr 18 07:42:01 2007 New Revision: 54866 Added: sandbox/trunk/2to3/fixes/fix_dummy.py (contents, props changed) Modified: sandbox/trunk/2to3/HACKING Log: Add a dummy fixer and advice on how to use it. Modified: sandbox/trunk/2to3/HACKING ============================================================================== --- sandbox/trunk/2to3/HACKING (original) +++ sandbox/trunk/2to3/HACKING Wed Apr 18 07:42:01 2007 @@ -6,6 +6,11 @@ * If your fixer works by changing a node's children list or a leaf's value, be sure to call the node/leaf's changed() method. This to be sure refactor.py will recognize that the tree has changed. + + * If you're making changes to pgen2, tokenize or any other part of the + parsing system (sometimes even pytree), you might want to check out + the 'dummy' fixer. It doesn't make any changes to the file, so you + just see what the parser does. Added: sandbox/trunk/2to3/fixes/fix_dummy.py ============================================================================== --- (empty file) +++ sandbox/trunk/2to3/fixes/fix_dummy.py Wed Apr 18 07:42:01 2007 @@ -0,0 +1,16 @@ +# Copyright 2007 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""This is a pass-through fixer. It can be useful when changing certain +parts of the parser or pytree.""" + +# Local imports +from fixes import basefix + +class FixDummy(basefix.BaseFix): + + def match(self, node): + return True + + def transform(self, node): + node.changed() From python-checkins at python.org Wed Apr 18 19:20:29 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 18 Apr 2007 19:20:29 +0200 (CEST) Subject: [Python-checkins] r54867 - peps/trunk/pep-0000.txt peps/trunk/pep-3119.txt Message-ID: <20070418172029.E0BDC1E4016@bag.python.org> Author: guido.van.rossum Date: Wed Apr 18 19:20:24 2007 New Revision: 54867 Added: peps/trunk/pep-3119.txt (contents, props changed) Modified: peps/trunk/pep-0000.txt Log: Claim PEP 3119 for the ABC PEP. Please disregard the contents for now. Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Wed Apr 18 19:20:24 2007 @@ -117,6 +117,7 @@ S 3116 New I/O Stutzbach, Verdone, GvR S 3117 Postfix Type Declarations Brandl S 3118 Revising the buffer protocol Oliphant, Banks + S 3119 Introducing Abstract Base Classes GvR, Talin Finished PEPs (done, implemented in Subversion) @@ -471,6 +472,7 @@ S 3116 New I/O Stutzbach, Verdone, GvR S 3117 Postfix Type Declarations Brandl S 3118 Revising the buffer protocol Oliphant, Banks + S 3119 Introducing Abstract Base Classes GvR, Talin Key Added: peps/trunk/pep-3119.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-3119.txt Wed Apr 18 19:20:24 2007 @@ -0,0 +1,108 @@ +PEP: 3119 +Title: Introducing Abstract Base Classes +Version: $Revision$ +Last-Modified: $Date$ +Author: Guido van Rossum , Talin +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 18-Apr-2007 +Post-History: 18-Apr-2007 + + +Abstract +======== + +This is a proposal to add Abstract Base Class support to Python 3000. + + +Rationale +========= + +In the domain of object-oriented programming, the usage patterns for +interacting with an object can be divided into two basic categories, +which are 'invocation' and 'inspection'. + +Invocation means interacting with an object by invoking its methods. +Usually this is combined with polymorphism, so that invoking a given +method may run different code depending on the type of an object. + +Inspection means the ability for external code (outside of the object's +methods) to examine the type or properties of that object, and make +decisions on how to treat that object based on that information. + +Both usage patterns serve the same general end, which is to be able to +support the processing of diverse and potentially novel objects in a +uniform way, but at the same time allowing processing decisions to be +customized for each different type of object. + +In classical OOP theory, invocation is the preferred usage pattern, and +inspection is actively discouraged, being considered a relic of an +earlier, procedural programming style. However, in practice this view is +simply too dogmatic and inflexible, and leads to a kind of design +rigidity that is very much at odds with the dynamic nature of a language +like Python. + +In particular, there is often a need to process objects in a way that +wasn't anticipated by the creator of the object class. It is not always +the best solution to build in to every object methods that satisfy the +needs of every possible user of that object. Moreover, there are many +powerful dispatch philosophies that are in direct contrast to the +classic OOP requirement of behavior being strictly encapsulated within +an object, examples being rule or pattern-match driven logic. + +On the the other hand, one of the criticisms of inspection by classic +OOP theorists is the lack of formalisms and the ad hoc nature of what is +being inspected. In a language such as Python, in which almost any +aspect of an object can be reflected and directly accessed by external +code, there are many different ways to test whether an object conforms +to a particular protocol or not. For example, if asking 'is this object +a mutable sequence container?', one can look for a base class of 'list', +or one can look for a method named '__getitem__'. But note that although +these tests may seem obvious, neither of them are correct, as one +generates false negatives, and the other false positives. + +The generally agreed-upon remedy is to standardize the tests, and group +them into a formal arrangement. This is most easily done by associating +with each class a set of standard testable properties, either via the +inheritance mechanism or some other means. Each test carries with it a +set of promises: it contains a promise about the general behavior of the +class, and a promise as to what other class methods will be available. + +This PEP proposes a particular strategy for organizing these tests known +as Abstract Base Classes, or ABC. ABCs are simply Python classes that +are added into an object's inheritance tree to signal certain features +of that object to an external inspector. Tests are done using +isinstance(), and the presence of a particular ABC means that the test +has passed. + +Like all other things in Python, these promises are in the nature of a +gentlemen's agreement - which means that the language does not attempt +to enforce that these promises are kept. + + +References +========== + +.. [1] An Introduction to ABC's, by Talin + (http://mail.python.org/pipermail/python-3000/2007-April/006614.html) + +.. [2] Incomplete implementation prototype, by GvR + (http://svn.python.org/view/sandbox/trunk/abc/) + + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: From python-checkins at python.org Wed Apr 18 19:32:24 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 18 Apr 2007 19:32:24 +0200 (CEST) Subject: [Python-checkins] r54868 - peps/trunk/pep-3119.txt Message-ID: <20070418173224.AF4A91E4017@bag.python.org> Author: guido.van.rossum Date: Wed Apr 18 19:32:21 2007 New Revision: 54868 Modified: peps/trunk/pep-3119.txt Log: Add a bit more to the abstract. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Wed Apr 18 19:32:21 2007 @@ -13,7 +13,20 @@ Abstract ======== -This is a proposal to add Abstract Base Class support to Python 3000. +This is a proposal to add Abstract Base Class (ABC) support to Python +3000. It proposes: + +* An "ABC support framework" which defines a metaclass, a base class, + a decorator, and some helpers that make it easy to define ABCs. + This will be added as a new library module named "abc". + +* Specific ABCs for containers and iterators, to be added to the + collections module. + +* Specific ABCs for numbers, to be added to a new module, yet to be + named. + +* Guidelines for writing additional ABCs. Rationale From python-checkins at python.org Wed Apr 18 19:43:07 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 18 Apr 2007 19:43:07 +0200 (CEST) Subject: [Python-checkins] r54869 - peps/trunk/pep-3119.txt Message-ID: <20070418174307.032DF1E400D@bag.python.org> Author: guido.van.rossum Date: Wed Apr 18 19:43:05 2007 New Revision: 54869 Modified: peps/trunk/pep-3119.txt Log: Clean up trailing whitespace. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Wed Apr 18 19:43:05 2007 @@ -32,65 +32,65 @@ Rationale ========= -In the domain of object-oriented programming, the usage patterns for -interacting with an object can be divided into two basic categories, +In the domain of object-oriented programming, the usage patterns for +interacting with an object can be divided into two basic categories, which are 'invocation' and 'inspection'. -Invocation means interacting with an object by invoking its methods. -Usually this is combined with polymorphism, so that invoking a given +Invocation means interacting with an object by invoking its methods. +Usually this is combined with polymorphism, so that invoking a given method may run different code depending on the type of an object. -Inspection means the ability for external code (outside of the object's -methods) to examine the type or properties of that object, and make +Inspection means the ability for external code (outside of the object's +methods) to examine the type or properties of that object, and make decisions on how to treat that object based on that information. -Both usage patterns serve the same general end, which is to be able to -support the processing of diverse and potentially novel objects in a -uniform way, but at the same time allowing processing decisions to be +Both usage patterns serve the same general end, which is to be able to +support the processing of diverse and potentially novel objects in a +uniform way, but at the same time allowing processing decisions to be customized for each different type of object. -In classical OOP theory, invocation is the preferred usage pattern, and -inspection is actively discouraged, being considered a relic of an -earlier, procedural programming style. However, in practice this view is -simply too dogmatic and inflexible, and leads to a kind of design -rigidity that is very much at odds with the dynamic nature of a language +In classical OOP theory, invocation is the preferred usage pattern, and +inspection is actively discouraged, being considered a relic of an +earlier, procedural programming style. However, in practice this view is +simply too dogmatic and inflexible, and leads to a kind of design +rigidity that is very much at odds with the dynamic nature of a language like Python. -In particular, there is often a need to process objects in a way that -wasn't anticipated by the creator of the object class. It is not always -the best solution to build in to every object methods that satisfy the -needs of every possible user of that object. Moreover, there are many -powerful dispatch philosophies that are in direct contrast to the -classic OOP requirement of behavior being strictly encapsulated within +In particular, there is often a need to process objects in a way that +wasn't anticipated by the creator of the object class. It is not always +the best solution to build in to every object methods that satisfy the +needs of every possible user of that object. Moreover, there are many +powerful dispatch philosophies that are in direct contrast to the +classic OOP requirement of behavior being strictly encapsulated within an object, examples being rule or pattern-match driven logic. -On the the other hand, one of the criticisms of inspection by classic -OOP theorists is the lack of formalisms and the ad hoc nature of what is -being inspected. In a language such as Python, in which almost any -aspect of an object can be reflected and directly accessed by external -code, there are many different ways to test whether an object conforms -to a particular protocol or not. For example, if asking 'is this object -a mutable sequence container?', one can look for a base class of 'list', -or one can look for a method named '__getitem__'. But note that although -these tests may seem obvious, neither of them are correct, as one +On the the other hand, one of the criticisms of inspection by classic +OOP theorists is the lack of formalisms and the ad hoc nature of what is +being inspected. In a language such as Python, in which almost any +aspect of an object can be reflected and directly accessed by external +code, there are many different ways to test whether an object conforms +to a particular protocol or not. For example, if asking 'is this object +a mutable sequence container?', one can look for a base class of 'list', +or one can look for a method named '__getitem__'. But note that although +these tests may seem obvious, neither of them are correct, as one generates false negatives, and the other false positives. -The generally agreed-upon remedy is to standardize the tests, and group -them into a formal arrangement. This is most easily done by associating -with each class a set of standard testable properties, either via the -inheritance mechanism or some other means. Each test carries with it a -set of promises: it contains a promise about the general behavior of the +The generally agreed-upon remedy is to standardize the tests, and group +them into a formal arrangement. This is most easily done by associating +with each class a set of standard testable properties, either via the +inheritance mechanism or some other means. Each test carries with it a +set of promises: it contains a promise about the general behavior of the class, and a promise as to what other class methods will be available. -This PEP proposes a particular strategy for organizing these tests known -as Abstract Base Classes, or ABC. ABCs are simply Python classes that -are added into an object's inheritance tree to signal certain features -of that object to an external inspector. Tests are done using -isinstance(), and the presence of a particular ABC means that the test +This PEP proposes a particular strategy for organizing these tests known +as Abstract Base Classes, or ABC. ABCs are simply Python classes that +are added into an object's inheritance tree to signal certain features +of that object to an external inspector. Tests are done using +isinstance(), and the presence of a particular ABC means that the test has passed. -Like all other things in Python, these promises are in the nature of a -gentlemen's agreement - which means that the language does not attempt +Like all other things in Python, these promises are in the nature of a +gentlemen's agreement - which means that the language does not attempt to enforce that these promises are kept. From python-checkins at python.org Wed Apr 18 20:39:32 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 18 Apr 2007 20:39:32 +0200 (CEST) Subject: [Python-checkins] r54870 - peps/trunk/pep-3119.txt Message-ID: <20070418183932.AE7031E4002@bag.python.org> Author: guido.van.rossum Date: Wed Apr 18 20:39:32 2007 New Revision: 54870 Modified: peps/trunk/pep-3119.txt Log: Add spec for abc module. Add more sections but with temporary contents. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Wed Apr 18 20:39:32 2007 @@ -94,6 +94,86 @@ to enforce that these promises are kept. +Specification +============= + +The specification follows the four categories listed in the abstract: + +* An "ABC support framework" which defines a metaclass, a base class, + a decorator, and some helpers that make it easy to define ABCs. + This will be added as a new library module named "abc". + +* Specific ABCs for containers and iterators, to be added to the + collections module. + +* Specific ABCs for numbers, to be added to a new module, yet to be + named. + +* Guidelines for writing additional ABCs. + + +ABC Support Framework +--------------------- + +The abc module will define some utilities that help defining ABCs. +These are: + +``@abstractmethod`` + A decorator to be used to declare abstract methods. This should + only be used with classes whose metaclass is (or is derived from) + ``AbstractClass`` below. A class containing at least one method + declared with this decorator that hasn't been overridden yet + cannot be instantiated. Such a methods may be called from the + overriding method in the subclass (using ``super`` or direct + invocation). + +``Abstract`` + A class implementing the constraint that it or its subclasses + cannot be instantiated unless each abstract method has been + overridden. Its metaclass is ``AbstractClass``. Note: being + derived from ``Abstract`` does not make a class abstract; the + abstract-ness is decided on a per-class basis, depending on + whether all methods defined with ``@abstractmethod`` have been + overridden. + +``AbstractClass`` + The metaclass of Abstract (and all classes derived from it). Its + purpose is to collect the information during the class + construction stage. It derives from ``type``. + +``AbstractInstantiationError`` + The exception raised when attempting to instantiate an abstract + class. It derives from ``TypeError``. + + +ABCs for Containers and Iterators +--------------------------------- + +XXX define: Iterable, Iterator, Sizeable (or Lengthy?), various Sets, +Mappings, Sequences. Also Hashable so we can define Immutable (which +adds to "read-only", does not subtract from "mutable", nor does +"mutable" add to "hashable" -- it adds to "read-only"). Also defines +how set, frozenset, list, tuple, dict, bytes and str derive from +these. + + +ABCs for Numbers +---------------- + +XXX define: Number, Complex, Real, Rational, Integer. Do we have a +use case for Cardinal (Integer >= 0)? Do we need Indexable (converts +to Integer using __index__). + + +Guidelines for Writing ABCs +--------------------------- + +XXX E.g. use @abstractmethod and Abstract base class; define abstract +methods that could be useful as an end point when called via a super +chain; keep abstract classes small, one per use case instead of one +per concept. + + References ========== From python-checkins at python.org Thu Apr 19 02:21:53 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 19 Apr 2007 02:21:53 +0200 (CEST) Subject: [Python-checkins] r54871 - peps/trunk/pep-3119.txt Message-ID: <20070419002153.6B2B81E4002@bag.python.org> Author: guido.van.rossum Date: Thu Apr 19 02:21:49 2007 New Revision: 54871 Modified: peps/trunk/pep-3119.txt Log: Add lots of text. Still far from complete. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Thu Apr 19 02:21:49 2007 @@ -7,7 +7,7 @@ Type: Standards Track Content-Type: text/x-rst Created: 18-Apr-2007 -Post-History: 18-Apr-2007 +Post-History: Not yet posted Abstract @@ -145,16 +145,266 @@ The exception raised when attempting to instantiate an abstract class. It derives from ``TypeError``. +A possible implementation would add an attribute +``__abstractmethod__`` to any method declared with +``@abstractmethod``, and add the names of all such abstract methods to +a class attribute named ``__abstractmethods__``. Then the +``Abstract.__new__()`` method would raise an exception if any abstract +methods exist on the class being instantiated. For details see [2]_. + ABCs for Containers and Iterators --------------------------------- -XXX define: Iterable, Iterator, Sizeable (or Lengthy?), various Sets, -Mappings, Sequences. Also Hashable so we can define Immutable (which -adds to "read-only", does not subtract from "mutable", nor does -"mutable" add to "hashable" -- it adds to "read-only"). Also defines -how set, frozenset, list, tuple, dict, bytes and str derive from -these. +The collections module will define ABCs necessary and sufficient to +work with sets, mappings, sequences, and some helper types such as +iterators and dictionary views. + +The ABCs provide implementations of their abstract methods that are +technically valid but fairly useless; e.g. ``__hash__`` returns 0, and +``__iter__`` returns an empty iterator. In general, the abstract +methods represent the behavior of an empty container of the indicated +type. + +Some ABCs also provide concrete (i.e. non-abstract) methods; for +example, the ``Iterator`` class has an ``__iter__`` method returning +itself, fulfilling an important invariant of iterators (which in +Python 2 has to be implemented anew by each iterator class). + +No ABCs override ``__init__``, ``__new__``, ``__str__`` or +``__repr__``. + +XXX define how set, frozenset, list, tuple, dict, bytes and str derive +from these. + + +One Trick Ponies +'''''''''''''''' + +These abstract classes represent single methods like ``__iter__`` or +``__len__``. + +``Hashable`` + The base class for classes defining ``__hash__``. Its abstract + ``__hash__`` method always returns 0, which is a valid (albeit + inefficient) implementation. Note: being an instance of this + class does not imply that an object is immutable; e.g. a tuple + containing a list as a member is not immutable; its ``__hash__`` + method raises an exception. + +``Iterable`` + The base class for classes defining ``__iter__``. Its abstract + ``__iter__`` method returns an empty iterator. + +``Iterator`` + The base class for classes defining ``__next__``. This derives + from ``Iterable``. Its abstract ``__next__`` method raises + StopIteration. Its ``__iter__`` method returns ``self``, and is + *not* abstract. + +``Lengthy`` + The base class for classes defining ``__len__``. Its abstract + ``__len__`` method returns 0. (The name is perhaps too cute; but + the only alternatives I've come up with so far are ``Sizeable``, + which suffers from the same affliction, and ``Finite``, which + somehow is associated with numbers instead of sets in my mind.) + +``Container`` + The base class for classes defining ``__contains__`. Its abstract + ``__contains__`` method returns ``False``. Note: strictly + speaking, there are three variants of this method's semantics. + The first one is for sets and mappings, which is fast: O(1) or + O(log N). The second one is for membership checking on sequences, + which is slow: O(N). The third one is for subsequence checking on + (character or byte) strings, which is also slow: O(N). Would it + make sense to distinguish these? The signature of the third + variant is different, since it takes a sequence (typically of the + same type as the method's target) intead of an element. For now, + I'm using the same type for all three. + + +Sets +'''' + +These abstract classes represent various stages of "set-ness". + +``Set`` + This is a finite, iterable container, i.e. a subclass of + ``Lengthy``, ``Iterable`` and ``Container``. Not every subset of + those three classes is a set though! Sets have the additional + property (though it is not expressed in code) that each element + occurs only once (as can be determined by iteration), and in + addition sets implement rich comparisons defined as + subclass/superclass tests. + + Sets with different implementations can be compared safely, + efficiently and correctly. Because ``Set`` derives from + ``Lengthy``, ``__eq__`` takes a shortcut and returns ``False`` + immediately if two sets of unequal length are compared. + Similarly, ``__le__`` returns ``False`` immediately if the first + set has more members than the second set. Note that set inclusion + implements only a partial ordering; e.g. {1, 2} and {1, 3} are not + ordered (all three of ``<``, ``==`` and ``>`` return ``False`` for + these arguments). Sets cannot be ordered relative to mappings or + sequences, but they can be compared for equality (and then they + always compare unequal). + + XXX Should we also implement the ``issubset`` and ``issuperset`` + methods found on the set type in Python 2 (which are apparently + just aliases for ``__le__`` and ``__ge__``)? + + XXX Should this class also implement union, intersection, + symmetric and asymmetric difference and/or the corresponding + operators? The problem with those (unlike the comparison + operators) is what should be the type of the return value. I'm + tentatively leaving these out -- if you need them, you can test + for a ``Set`` instance that implements e.g. ``__and__``. Some + alternatives: make these abstract methods (even though the + semantics apart from the type are well-defined); or make them + concrete methods that return a specific concrete set type; or make + them concrete methods that assume the class constructor always + accepts an iterable of elements; or add a new class method that + accepts an iterable of elements and that creates a new instance. + (I originally considered a "view" alternative, but the problem is + that computing ``len(a&b)`` requires iterating over ``a`` or + ``b``, and that pretty much kills the idea.) + +``HashableSet`` + This is a subclass of both ``Set`` and ``Hashable``. It + implements a concrete ``__hash__`` method that subclasses should + not override; or if they do, the subclass should compute the same + hash value. This is so that sets with different implementations + still hash to the same value, so they can be used interchangeably + as dictionary keys. (A similar constraint exists on the hash + values for different types of numbers and strings.) + +``MutableSet`` + + This is a subclass of ``Set`` implementing additional operations + to add and remove elements. The supported methods have the + semantics known from the ``set`` type in Python 2: + + ``.add(x)`` + Abstract method that adds the element ``x``, if it isn't + already in the set. + + ``.remove(x)`` + + Abstract method that removes the element ``x``; raises + ``KeyError`` if ``x`` is not in the set. + + ``.discard(x)`` + Concrete method that removes the element ``x`` if it is + a member of the set; implemented using ``__contains__`` + and ``remove``. + + ``.clear()`` + Abstract method that empties the set. (Making this concrete + would just add a slow, cumbersome default implementation.) + + XXX Should we support all the operations implemented by the Python + 2 ``set`` type? I.e. union, update, __or__, __ror__, __ior__, + intersection, intersection_update, __and__, __rand__, __iand__, + difference, difference_update, __xor__, __rxor__, __ixor__, + symmetric_difference, symmetric_difference_update, __sub__, + __rsub__, __isub__. Note that in Python 2, a.update(b) is not + exactly the same as a |= b, since update() takes any iterable for + an argument, while |= requires another set; similar for the other + operators. + + +Mappings +'''''''' + +These abstract classes represent various stages of mapping-ness. + +XXX Do we need BasicMapping and IterableMapping? Perhaps we should +just start with Mapping. + +``BasicMapping`` + A subclass of ``Container`` defining the following methods: + + ``.__getitem__(key)`` + Abstract method that returns the value corresponding to + ``key``, or raises ``KeyError``. The implementation always + raises ``KeyError``. + + ``.get(key, default=None)`` + Concrete method returning ``self[key]`` if this does not raise + ``KeyError``, and the ``default`` value if it does. + + ``.__contains__()`` + Concrete method returning ``True`` if ``self[key]`` does not + raise ``KeyError``, and ``False`` if it does. + + +``IterableMapping`` + A subclass of ``BasicMapping`` and ``Iterable``. It defines no + new methods. Iterating over such an object should return all the + valid keys (i.e. those keys for which ``.__getitem__()`` returns a + value), once each, and nothing else. It is possible that the + iteration never ends. + +``Mapping`` + A subclass of ``IterableMapping`` and ``Lengthy``. It defines + concrete methods ``__eq__``, ``keys``, ``items``, ``values``. The + lengh of such an object should equal to the number of elements + returned by iterating over the object until the end of the + iterator is reached. Two mappings, even with different + implementations, can be compared for equality, and are considered + equal if and only iff their items compare equal when converted to + sets. The ``keys``, ``items`` and ``values`` methods return + views; ``keys`` and ``items`` return ``Set`` views, ``values`` + returns a ``Container`` view. The following invariant should + hold: m.items() == set(zip(m.keys(), m.values())). + +``HashableMapping`` + A subclass of ``Mapping`` and ``Hashable``. The values should be + instances of ``Hashable``. The concrete ``__hash__`` method + should be equal to ``hash(m.items())``. + +``MutableMapping`` + A subclass of ``Mapping`` that also implements some standard + mutating methods. At least ``__setitem__``, ``__delitem__``, + ``clear``, ``update``. XXX Also pop, popitem, setdefault? + +XXX Should probably say something about mapping view types, too. + +Sequences +''''''''' + +These abstract classes represent various stages of sequence-ness. + +``Sequence`` + A subclass of ``Iterable``, ``Lengthy``, ``Container``. It + defines a new abstract method ``__getitem__`` that has a + complicated signature: when called with an integer, it returns an + element of the sequence or raises ``IndexError``; when called with + a ``slice`` object, it returns another ``Sequence``. The concrete + ``__iter__`` method iterates over the elements using + ``__getitem__`` with integer arguments 0, 1, and so on, until + ``IndexError`` is raised. The length should be equal to the + number of values returned by the iterator. + + XXX Other candidate methods, which can all have default concrete + implementations that only depend on ``__len__`` and + ``__getitem__`` with an integer argument: __reversed__, index, + count, __add__, __mul__, __eq__, __lt__, __le__. + +``HashableSequence`` + A subclass of ``Sequence`` and ``Hashable``. The concrete + ``__hash__`` method should implements the hashing algorithms used + by tuples in Python 2. + +``MutableSequence`` + A subclass of ``Sequence`` adding some standard mutating methods. + Abstract mutating methods: ``__setitem__`` (for integer indices as + well as slices), ``__delitem__`` (ditto), ``insert``, ``add``, + ``reverse``. Concrete mutating methods: ``extend``, ``pop``, + ``remove``. Note: this does not define ``sort()`` -- that is only + required to exist on genuine ``list`` instances. + + XXX What about += and *=? ABCs for Numbers @@ -168,10 +418,11 @@ Guidelines for Writing ABCs --------------------------- -XXX E.g. use @abstractmethod and Abstract base class; define abstract +XXX Use @abstractmethod and Abstract base class; define abstract methods that could be useful as an end point when called via a super -chain; keep abstract classes small, one per use case instead of one -per concept. +chain; define concrete methods that are very simple permutations of +abstract methods (e.g. Mapping.get); keep abstract classes small, one +per use case instead of one per concept. References From python-checkins at python.org Thu Apr 19 02:33:06 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 19 Apr 2007 02:33:06 +0200 (CEST) Subject: [Python-checkins] r54872 - peps/trunk/pep-3119.txt Message-ID: <20070419003306.88AE61E4002@bag.python.org> Author: guido.van.rossum Date: Thu Apr 19 02:33:02 2007 New Revision: 54872 Modified: peps/trunk/pep-3119.txt Log: Fix rest warnings. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Thu Apr 19 02:33:02 2007 @@ -307,10 +307,10 @@ intersection, intersection_update, __and__, __rand__, __iand__, difference, difference_update, __xor__, __rxor__, __ixor__, symmetric_difference, symmetric_difference_update, __sub__, - __rsub__, __isub__. Note that in Python 2, a.update(b) is not - exactly the same as a |= b, since update() takes any iterable for - an argument, while |= requires another set; similar for the other - operators. + __rsub__, __isub__. Note that in Python 2, ``a.update(b)`` is not + exactly the same as ``a |= b``, since ``update()`` takes any + iterable for an argument, while ``|=`` requires another set; + similar for the other operators. Mappings @@ -404,7 +404,7 @@ ``remove``. Note: this does not define ``sort()`` -- that is only required to exist on genuine ``list`` instances. - XXX What about += and *=? + XXX What about ``+=`` and ``*=``? ABCs for Numbers From python-checkins at python.org Thu Apr 19 05:44:23 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 19 Apr 2007 05:44:23 +0200 (CEST) Subject: [Python-checkins] r54873 - python/trunk/Objects/frameobject.c Message-ID: <20070419034423.218DF1E4002@bag.python.org> Author: brett.cannon Date: Thu Apr 19 05:44:17 2007 New Revision: 54873 Modified: python/trunk/Objects/frameobject.c Log: Silence a compiler warning about incompatible pointer types. Modified: python/trunk/Objects/frameobject.c ============================================================================== --- python/trunk/Objects/frameobject.c (original) +++ python/trunk/Objects/frameobject.c Thu Apr 19 05:44:17 2007 @@ -137,7 +137,7 @@ } /* We're now ready to look at the bytecode. */ - PyString_AsStringAndSize(f->f_code->co_code, &code, &code_len); + PyString_AsStringAndSize(f->f_code->co_code, (char **)&code, &code_len); min_addr = MIN(new_lasti, f->f_lasti); max_addr = MAX(new_lasti, f->f_lasti); From python-checkins at python.org Thu Apr 19 07:52:38 2007 From: python-checkins at python.org (neal.norwitz) Date: Thu, 19 Apr 2007 07:52:38 +0200 (CEST) Subject: [Python-checkins] r54874 - python/trunk/Modules/readline.c Message-ID: <20070419055238.0B7BD1E4010@bag.python.org> Author: neal.norwitz Date: Thu Apr 19 07:52:37 2007 New Revision: 54874 Modified: python/trunk/Modules/readline.c Log: SF #1703270, add missing declaration in readline.c to avoid compiler warning. Modified: python/trunk/Modules/readline.c ============================================================================== --- python/trunk/Modules/readline.c (original) +++ python/trunk/Modules/readline.c Thu Apr 19 07:52:37 2007 @@ -34,6 +34,8 @@ #ifdef HAVE_RL_COMPLETION_MATCHES #define completion_matches(x, y) \ rl_completion_matches((x), ((rl_compentry_func_t *)(y))) +#else +extern char **completion_matches(char *, rl_compentry_func_t *); #endif @@ -632,7 +634,7 @@ /* C function to call the Python completer. */ static char * -on_completion(char *text, int state) +on_completion(const char *text, int state) { char *result = NULL; if (completer != NULL) { From buildbot at python.org Thu Apr 19 08:17:14 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 19 Apr 2007 06:17:14 +0000 Subject: [Python-checkins] buildbot warnings in x86 mvlgcc trunk Message-ID: <20070419061714.DBAAD1E4002@bag.python.org> The Buildbot has detected a new failure of x86 mvlgcc trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520mvlgcc%2520trunk/builds/470 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: neal.norwitz Build had warnings: warnings test Excerpt from the test logfile: Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 93, in run svr.serve_a_few() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 35, in serve_a_few self.handle_request() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 224, in handle_request self.handle_error(request, client_address) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 222, in handle_request self.process_request(request, client_address) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 429, in process_request self.collect_children() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 425, in collect_children self.active_children.remove(pid) ValueError: list.remove(x): x not in list 1 test failed: test_socketserver make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Apr 19 16:44:54 2007 From: python-checkins at python.org (armin.rigo) Date: Thu, 19 Apr 2007 16:44:54 +0200 (CEST) Subject: [Python-checkins] r54875 - in python/trunk: Lib/test/test_descr.py Objects/typeobject.c Message-ID: <20070419144454.AC4C11E401D@bag.python.org> Author: armin.rigo Date: Thu Apr 19 16:44:48 2007 New Revision: 54875 Modified: python/trunk/Lib/test/test_descr.py python/trunk/Objects/typeobject.c Log: Revert r53997 as per http://mail.python.org/pipermail/python-dev/2007-March/071796.html . I've kept a couple of still-valid extra tests in test_descr, but didn't bother to sort through the new comments and refactorings added in r53997 to see if some of them could be kept. If so, they could go in a follow-up check-in. Modified: python/trunk/Lib/test/test_descr.py ============================================================================== --- python/trunk/Lib/test/test_descr.py (original) +++ python/trunk/Lib/test/test_descr.py Thu Apr 19 16:44:48 2007 @@ -1,6 +1,6 @@ # Test enhancements related to descriptors and new-style classes -from test.test_support import verify, vereq, verbose, TestFailed, TESTFN, get_original_stdout, run_doctest +from test.test_support import verify, vereq, verbose, TestFailed, TESTFN, get_original_stdout from copy import deepcopy import warnings @@ -1466,89 +1466,65 @@ verify(someclass != object) def errors(): - """Test that type can't be placed after an instance of type in bases. + if verbose: print "Testing errors..." - >>> class C(list, dict): - ... pass - Traceback (most recent call last): - TypeError: Error when calling the metaclass bases - multiple bases have instance lay-out conflict - - >>> class C(object, None): - ... pass - Traceback (most recent call last): - TypeError: Error when calling the metaclass bases - bases must be types - - >>> class C(type(len)): - ... pass - Traceback (most recent call last): - TypeError: Error when calling the metaclass bases - type 'builtin_function_or_method' is not an acceptable base type - - >>> class Classic: - ... def __init__(*args): pass - >>> class C(object): - ... __metaclass__ = Classic - - >>> class C(object): - ... __slots__ = 1 - Traceback (most recent call last): - TypeError: Error when calling the metaclass bases - 'int' object is not iterable - - >>> class C(object): - ... __slots__ = [1] - Traceback (most recent call last): - TypeError: Error when calling the metaclass bases - __slots__ items must be strings, not 'int' - - >>> class A(object): - ... pass - - >>> class B(A, type): - ... pass - Traceback (most recent call last): - TypeError: Error when calling the metaclass bases - metaclass conflict: type must occur in bases before other non-classic base classes - - Create two different metaclasses in order to setup an error where - there is no inheritance relationship between the metaclass of a class - and the metaclass of its bases. - - >>> class M1(type): - ... pass - >>> class M2(type): - ... pass - >>> class A1(object): - ... __metaclass__ = M1 - >>> class A2(object): - ... __metaclass__ = M2 - >>> class B(A1, A2): - ... pass - Traceback (most recent call last): - TypeError: Error when calling the metaclass bases - metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases - >>> class B(A1): - ... pass - - Also check that assignment to bases is safe. - - >>> B.__bases__ = A1, A2 - Traceback (most recent call last): - TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases - >>> B.__bases__ = A2, - Traceback (most recent call last): - TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases - - >>> class M3(M1): - ... pass - >>> class C(object): - ... __metaclass__ = M3 - >>> B.__bases__ = C, - Traceback (most recent call last): - TypeError: assignment to __bases__ may not change metatype - """ + try: + class C(list, dict): + pass + except TypeError: + pass + else: + verify(0, "inheritance from both list and dict should be illegal") + + try: + class C(object, None): + pass + except TypeError: + pass + else: + verify(0, "inheritance from non-type should be illegal") + class Classic: + pass + + try: + class C(type(len)): + pass + except TypeError: + pass + else: + verify(0, "inheritance from CFunction should be illegal") + + try: + class C(object): + __slots__ = 1 + except TypeError: + pass + else: + verify(0, "__slots__ = 1 should be illegal") + + try: + class C(object): + __slots__ = [1] + except TypeError: + pass + else: + verify(0, "__slots__ = [1] should be illegal") + + class M1(type): + pass + class M2(type): + pass + class A1(object): + __metaclass__ = M1 + class A2(object): + __metaclass__ = M2 + try: + class B(A1, A2): + pass + except TypeError: + pass + else: + verify(0, "finding the most derived metaclass should have failed") def classmethods(): if verbose: print "Testing class methods..." @@ -4331,6 +4307,7 @@ slots() slotspecials() dynamics() + errors() classmethods() classmethods_in_c() staticmethods() @@ -4399,9 +4376,6 @@ notimplemented() test_assign_slice() - from test import test_descr - run_doctest(test_descr, verbosity=True) - if verbose: print "All OK" if __name__ == "__main__": Modified: python/trunk/Objects/typeobject.c ============================================================================== --- python/trunk/Objects/typeobject.c (original) +++ python/trunk/Objects/typeobject.c Thu Apr 19 16:44:48 2007 @@ -127,7 +127,6 @@ return type->tp_bases; } -static PyTypeObject *most_derived_metaclass(PyTypeObject *, PyObject *); static PyTypeObject *best_base(PyObject *); static int mro_internal(PyTypeObject *); static int compatible_for_assignment(PyTypeObject *, PyTypeObject *, char *); @@ -188,7 +187,7 @@ Py_ssize_t i; int r = 0; PyObject *ob, *temp; - PyTypeObject *new_base, *old_base, *metatype; + PyTypeObject *new_base, *old_base; PyObject *old_bases, *old_mro; if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { @@ -231,17 +230,6 @@ } } - - metatype = most_derived_metaclass(type->ob_type, value); - if (metatype == NULL) - return -1; - if (metatype != type->ob_type) { - PyErr_SetString(PyExc_TypeError, - "assignment to __bases__ may not change " - "metatype"); - return -1; - } - new_base = best_base(value); if (!new_base) { @@ -1367,14 +1355,7 @@ /* Calculate the best base amongst multiple base classes. - This is the first one that's on the path to the "solid base". - - Requires that all base classes be types or classic classes. - - Will return NULL with TypeError set if - 1) the base classes have conflicting layout instances, or - 2) all the bases are classic classes. -*/ + This is the first one that's on the path to the "solid base". */ static PyTypeObject * best_base(PyObject *bases) @@ -1392,7 +1373,12 @@ base_proto = PyTuple_GET_ITEM(bases, i); if (PyClass_Check(base_proto)) continue; - assert(PyType_Check(base_proto)); + if (!PyType_Check(base_proto)) { + PyErr_SetString( + PyExc_TypeError, + "bases must be types"); + return NULL; + } base_i = (PyTypeObject *)base_proto; if (base_i->tp_dict == NULL) { if (PyType_Ready(base_i) < 0) @@ -1445,8 +1431,6 @@ return t_size != b_size; } -/* Return the type object that will determine the layout of the instance. */ - static PyTypeObject * solid_base(PyTypeObject *type) { @@ -1462,71 +1446,6 @@ return base; } -/* Determine the proper metatype to deal with this, and check some - error cases while we're at it. Note that if some other metatype - wins to contract, it's possible that its instances are not types. - - Error cases of interest: 1. The metaclass is not a subclass of a - base class. 2. A non-type, non-classic base class appears before - type. -*/ - -static PyTypeObject * -most_derived_metaclass(PyTypeObject *metatype, PyObject *bases) -{ - Py_ssize_t nbases, i; - PyTypeObject *winner; - /* types_ordered: One of three states possible: - 0 type is in bases - 1 non-types also in bases - 2 type follows non-type in bases (error) - */ - int types_ordered = 0; - - nbases = PyTuple_GET_SIZE(bases); - winner = metatype; - for (i = 0; i < nbases; i++) { - PyObject *tmp = PyTuple_GET_ITEM(bases, i); - PyTypeObject *tmptype = tmp->ob_type; - if (tmptype == &PyClass_Type) - continue; /* Special case classic classes */ - if (!PyType_Check(tmp)) { - PyErr_SetString(PyExc_TypeError, - "bases must be types"); - return NULL; - } - if (PyObject_IsSubclass(tmp, (PyObject*)&PyType_Type)) { - if (types_ordered == 1) { - types_ordered = 2; - } - } - else if (!types_ordered) - types_ordered = 1; - if (winner == tmptype) - continue; - if (PyType_IsSubtype(winner, tmptype)) - continue; - if (PyType_IsSubtype(tmptype, winner)) { - winner = tmptype; - continue; - } - PyErr_SetString(PyExc_TypeError, - "metaclass conflict: " - "the metaclass of a derived class " - "must be a (non-strict) subclass " - "of the metaclasses of all its bases"); - return NULL; - } - if (types_ordered == 2) { - PyErr_SetString(PyExc_TypeError, - "metaclass conflict: " - "type must occur in bases before other " - "non-classic base classes"); - return NULL; - } - return winner; -} - static void object_dealloc(PyObject *); static int object_init(PyObject *, PyObject *, PyObject *); static int update_slot(PyTypeObject *, PyObject *); @@ -1760,18 +1679,37 @@ &PyDict_Type, &dict)) return NULL; - winner = most_derived_metaclass(metatype, bases); - if (winner == NULL) + /* Determine the proper metatype to deal with this, + and check for metatype conflicts while we're at it. + Note that if some other metatype wins to contract, + it's possible that its instances are not types. */ + nbases = PyTuple_GET_SIZE(bases); + winner = metatype; + for (i = 0; i < nbases; i++) { + tmp = PyTuple_GET_ITEM(bases, i); + tmptype = tmp->ob_type; + if (tmptype == &PyClass_Type) + continue; /* Special case classic classes */ + if (PyType_IsSubtype(winner, tmptype)) + continue; + if (PyType_IsSubtype(tmptype, winner)) { + winner = tmptype; + continue; + } + PyErr_SetString(PyExc_TypeError, + "metaclass conflict: " + "the metaclass of a derived class " + "must be a (non-strict) subclass " + "of the metaclasses of all its bases"); return NULL; + } if (winner != metatype) { - if (winner->tp_new != type_new) /* Pass it to the winner */ { + if (winner->tp_new != type_new) /* Pass it to the winner */ return winner->tp_new(winner, args, kwds); - } metatype = winner; } /* Adjust for empty tuple bases */ - nbases = PyTuple_GET_SIZE(bases); if (nbases == 0) { bases = PyTuple_Pack(1, &PyBaseObject_Type); if (bases == NULL) From python-checkins at python.org Thu Apr 19 16:56:56 2007 From: python-checkins at python.org (armin.rigo) Date: Thu, 19 Apr 2007 16:56:56 +0200 (CEST) Subject: [Python-checkins] r54876 - python/trunk/Objects/typeobject.c Message-ID: <20070419145656.0F6A11E4002@bag.python.org> Author: armin.rigo Date: Thu Apr 19 16:56:48 2007 New Revision: 54876 Modified: python/trunk/Objects/typeobject.c Log: Fix a usage of the dangerous pattern decref - modify field - incref. Modified: python/trunk/Objects/typeobject.c ============================================================================== --- python/trunk/Objects/typeobject.c (original) +++ python/trunk/Objects/typeobject.c Thu Apr 19 16:56:48 2007 @@ -265,9 +265,10 @@ PyObject* mro; PyArg_UnpackTuple(PyList_GET_ITEM(temp, i), "", 2, 2, &cls, &mro); - Py_DECREF(cls->tp_mro); + Py_INCREF(mro); + ob = cls->tp_mro; cls->tp_mro = mro; - Py_INCREF(cls->tp_mro); + Py_DECREF(ob); } Py_DECREF(temp); goto bail; From buildbot at python.org Thu Apr 19 19:35:43 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 19 Apr 2007 17:35:43 +0000 Subject: [Python-checkins] buildbot warnings in hppa Ubuntu dapper trunk Message-ID: <20070419173543.B09F51E4002@bag.python.org> The Buildbot has detected a new failure of hppa Ubuntu dapper trunk. Full details are available at: http://www.python.org/dev/buildbot/all/hppa%2520Ubuntu%2520dapper%2520trunk/builds/167 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: armin.rigo Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Thu Apr 19 19:58:48 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 19 Apr 2007 19:58:48 +0200 (CEST) Subject: [Python-checkins] r54877 - peps/trunk/pep-3119.txt Message-ID: <20070419175848.98B581E4002@bag.python.org> Author: guido.van.rossum Date: Thu Apr 19 19:58:47 2007 New Revision: 54877 Modified: peps/trunk/pep-3119.txt Log: Checkpoint. Use Finite for the class defining __len__. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Thu Apr 19 19:58:47 2007 @@ -2,7 +2,7 @@ Title: Introducing Abstract Base Classes Version: $Revision$ Last-Modified: $Date$ -Author: Guido van Rossum , Talin +Author: Guido van Rossum , Talin Status: Draft Type: Standards Track Content-Type: text/x-rst @@ -13,6 +13,8 @@ Abstract ======== +**THIS IS A WORK IN PROGRESS! DON'T REVIEW YET!** + This is a proposal to add Abstract Base Class (ABC) support to Python 3000. It proposes: @@ -28,6 +30,11 @@ * Guidelines for writing additional ABCs. +Much of the thinking that went into the proposal is not about the +specific mechanism of ABCs, as contrasted with Interfaces or Generic +Functions (GFs), but about clarifying philosophical issues like "what +makes a set", "what makes a mapping" and "what makes a sequence". + Rationale ========= @@ -120,12 +127,11 @@ ``@abstractmethod`` A decorator to be used to declare abstract methods. This should - only be used with classes whose metaclass is (or is derived from) - ``AbstractClass`` below. A class containing at least one method - declared with this decorator that hasn't been overridden yet - cannot be instantiated. Such a methods may be called from the - overriding method in the subclass (using ``super`` or direct - invocation). + only be used with classes whose class is derived from ``Abstract`` + below. A class containing at least one method declared with this + decorator that hasn't been overridden yet cannot be instantiated. + Such a methods may be called from the overriding method in the + subclass (using ``super`` or direct invocation). ``Abstract`` A class implementing the constraint that it or its subclasses @@ -152,6 +158,11 @@ ``Abstract.__new__()`` method would raise an exception if any abstract methods exist on the class being instantiated. For details see [2]_. +**Open issue:** perhaps ``abstractmethod`` and +``AbstractInstantiationError`` should become built-ins, ``Abstract``'s +functionality should be subsumed by ``object``, and +``AbstractClass``'s functionality should be merged into ``type``. + ABCs for Containers and Iterators --------------------------------- @@ -199,28 +210,29 @@ ``Iterator`` The base class for classes defining ``__next__``. This derives from ``Iterable``. Its abstract ``__next__`` method raises - StopIteration. Its ``__iter__`` method returns ``self``, and is - *not* abstract. + ``StopIteration``. Its ``__iter__`` method returns ``self``, and + is *not* abstract. (Note: this assumes PEP 3114 is implemented.) -``Lengthy`` +``Finite`` The base class for classes defining ``__len__``. Its abstract - ``__len__`` method returns 0. (The name is perhaps too cute; but - the only alternatives I've come up with so far are ``Sizeable``, - which suffers from the same affliction, and ``Finite``, which - somehow is associated with numbers instead of sets in my mind.) + ``__len__`` method returns 0. Any ``__len__`` method should + return an ``Integer`` (see "Numbers" below) >= 0. If class ``C`` + derives from ``Finite`` as well as from ``Iterable``, the + invariant ``sum(1 for x in o) == len(o)`` should hold for any + instance ``o`` of ``C``. ``Container`` - The base class for classes defining ``__contains__`. Its abstract - ``__contains__`` method returns ``False``. Note: strictly - speaking, there are three variants of this method's semantics. - The first one is for sets and mappings, which is fast: O(1) or - O(log N). The second one is for membership checking on sequences, - which is slow: O(N). The third one is for subsequence checking on - (character or byte) strings, which is also slow: O(N). Would it - make sense to distinguish these? The signature of the third - variant is different, since it takes a sequence (typically of the - same type as the method's target) intead of an element. For now, - I'm using the same type for all three. + The base class for classes defining ``__contains__``. Its + abstract ``__contains__`` method returns ``False``. Note: + strictly speaking, there are three variants of this method's + semantics. The first one is for sets and mappings, which is fast: + O(1) or O(log N). The second one is for membership checking on + sequences, which is slow: O(N). The third one is for subsequence + checking on (character or byte) strings, which is also slow: O(N). + Would it make sense to distinguish these? The signature of the + third variant is different, since it takes a sequence (typically + of the same type as the method's target) intead of an element. + For now, I'm using the same type for all three. Sets @@ -230,7 +242,7 @@ ``Set`` This is a finite, iterable container, i.e. a subclass of - ``Lengthy``, ``Iterable`` and ``Container``. Not every subset of + ``Finite``, ``Iterable`` and ``Container``. Not every subset of those three classes is a set though! Sets have the additional property (though it is not expressed in code) that each element occurs only once (as can be determined by iteration), and in @@ -239,7 +251,7 @@ Sets with different implementations can be compared safely, efficiently and correctly. Because ``Set`` derives from - ``Lengthy``, ``__eq__`` takes a shortcut and returns ``False`` + ``Finite``, ``__eq__`` takes a shortcut and returns ``False`` immediately if two sets of unequal length are compared. Similarly, ``__le__`` returns ``False`` immediately if the first set has more members than the second set. Note that set inclusion @@ -346,7 +358,7 @@ iteration never ends. ``Mapping`` - A subclass of ``IterableMapping`` and ``Lengthy``. It defines + A subclass of ``IterableMapping`` and ``Finite``. It defines concrete methods ``__eq__``, ``keys``, ``items``, ``values``. The lengh of such an object should equal to the number of elements returned by iterating over the object until the end of the @@ -376,7 +388,7 @@ These abstract classes represent various stages of sequence-ness. ``Sequence`` - A subclass of ``Iterable``, ``Lengthy``, ``Container``. It + A subclass of ``Iterable``, ``Finite``, ``Container``. It defines a new abstract method ``__getitem__`` that has a complicated signature: when called with an integer, it returns an element of the sequence or raises ``IndexError``; when called with From python-checkins at python.org Thu Apr 19 20:53:53 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 19 Apr 2007 20:53:53 +0200 (CEST) Subject: [Python-checkins] r54878 - peps/trunk/pep-3119.txt Message-ID: <20070419185353.3AA171E4002@bag.python.org> Author: guido.van.rossum Date: Thu Apr 19 20:53:49 2007 New Revision: 54878 Modified: peps/trunk/pep-3119.txt Log: Another checkpoint. Add some invariants. Resolve an XXX or two. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Thu Apr 19 20:53:49 2007 @@ -108,13 +108,14 @@ * An "ABC support framework" which defines a metaclass, a base class, a decorator, and some helpers that make it easy to define ABCs. - This will be added as a new library module named "abc". + This will be added as a new library module named "abc", or (perhaps) + made built-in functionality. * Specific ABCs for containers and iterators, to be added to the collections module. -* Specific ABCs for numbers, to be added to a new module, yet to be - named. +* Specific ABCs for numbers, to be added to a new module that is yet + to be named. * Guidelines for writing additional ABCs. @@ -126,13 +127,13 @@ These are: ``@abstractmethod`` - A decorator to be used to declare abstract methods. This should - only be used with classes whose class is derived from ``Abstract`` - below. A class containing at least one method declared with this + A decorator used to declare abstract methods. This should only be + used with classes whose class is derived from ``Abstract`` below. + A class containing at least one method declared with this decorator that hasn't been overridden yet cannot be instantiated. Such a methods may be called from the overriding method in the subclass (using ``super`` or direct invocation). - + ``Abstract`` A class implementing the constraint that it or its subclasses cannot be instantiated unless each abstract method has been @@ -185,46 +186,57 @@ No ABCs override ``__init__``, ``__new__``, ``__str__`` or ``__repr__``. -XXX define how set, frozenset, list, tuple, dict, bytes and str derive -from these. - One Trick Ponies '''''''''''''''' These abstract classes represent single methods like ``__iter__`` or -``__len__``. +``__len__``. The ``Iterator`` class is included as well, even though +it has two prescribed methods. ``Hashable`` - The base class for classes defining ``__hash__``. Its abstract - ``__hash__`` method always returns 0, which is a valid (albeit - inefficient) implementation. Note: being an instance of this - class does not imply that an object is immutable; e.g. a tuple - containing a list as a member is not immutable; its ``__hash__`` - method raises an exception. + + The base class for classes defining ``__hash__``. The + ``__hash__`` method should return an ``Integer`` (see "Numbers" + below). The abstract ``__hash__`` method always returns 0, which + is a valid (albeit inefficient) implementation. **Invariant:** If + classes ``C1`` and ``C2`` both derive from ``Hashable``, the + invariant ``hash(o1) == hash(o2)`` must imply ``o1 == o2`` for all + instances ``o1`` of ``C1`` and all instances ``o2`` of ``C2``. + + Note: being an instance of this class does not imply that an + object is immutable; e.g. a tuple containing a list as a member is + not immutable; its ``__hash__`` method raises an exception. ``Iterable`` - The base class for classes defining ``__iter__``. Its abstract - ``__iter__`` method returns an empty iterator. + The base class for classes defining ``__iter__``. The + ``__iter__`` method should always return an instance of + ``Iterator`` (see below). The abstract ``__iter__`` method + returns an empty iterator. ``Iterator`` The base class for classes defining ``__next__``. This derives - from ``Iterable``. Its abstract ``__next__`` method raises - ``StopIteration``. Its ``__iter__`` method returns ``self``, and - is *not* abstract. (Note: this assumes PEP 3114 is implemented.) + from ``Iterable``. The abstract ``__next__`` method raises + ``StopIteration``. The concrete ``__iter__`` method returns + ``self``. (Note: this assumes PEP 3114 is implemented.) ``Finite`` - The base class for classes defining ``__len__``. Its abstract - ``__len__`` method returns 0. Any ``__len__`` method should - return an ``Integer`` (see "Numbers" below) >= 0. If class ``C`` - derives from ``Finite`` as well as from ``Iterable``, the - invariant ``sum(1 for x in o) == len(o)`` should hold for any + The base class for classes defining ``__len__``. The ``__len__`` + method should return an ``Integer`` (see "Numbers" below) >= 0. + The abstract ``__len__`` method returns 0. **Invariant:** If a + class ``C`` derives from ``Finite`` as well as from ``Iterable``, + the invariant ``sum(1 for x in o) == len(o)`` should hold for any instance ``o`` of ``C``. ``Container`` - The base class for classes defining ``__contains__``. Its - abstract ``__contains__`` method returns ``False``. Note: - strictly speaking, there are three variants of this method's + The base class for classes defining ``__contains__``. The + ``__contains__` method should return a ``bool``.` The abstract + ``__contains__`` method returns ``False``. **Invariant:** If a + class ``C`` derives from ``Container`` as well as from + ``Iterable``, ``(x in o for x in o)`` should be a generator + yielding only True values for any instance ``o`` of ``C``. + + Note: strictly speaking, there are three variants of this method's semantics. The first one is for sets and mappings, which is fast: O(1) or O(log N). The second one is for membership checking on sequences, which is slow: O(N). The third one is for subsequence @@ -232,22 +244,44 @@ Would it make sense to distinguish these? The signature of the third variant is different, since it takes a sequence (typically of the same type as the method's target) intead of an element. - For now, I'm using the same type for all three. + For now, I'm using the same type for all three. This means that + is is possible for ``x in o`` to be True even though ``x`` is + never yielded by ``iter(o)``. Sets '''' -These abstract classes represent various stages of "set-ness". +These abstract classes represent various stages of "set-ness". The +most fundamental set operation is the membership test, written as ``x +in s`` and implemented by ``s.__contains__(x)``. This is already +taken care of by the `Container`` class defined above. Therefore, we +define a set as finite, iterable container for which certain +invariants from mathematical set theory hold. + +The built-in type ``set`` derives from ``MutableSet``. The built-in +type ``frozenset`` derives from ``HashableSet``. + +You might wonder why we require a set to be finite -- surely certain +infinite sets can be represented just fine in Python. For example, +the set of even integers could be defined like this:: + + class EvenIntegers(Container): + def __contains__(self, x): + return x % 2 == 0 + +However, such sets have rather limited practical value, and deciding +whether one such set is a subset of another would be difficult in +general without using a symbolic algebra package. So I consider this +out of the scope of a pragmatic proposal like this. ``Set`` This is a finite, iterable container, i.e. a subclass of ``Finite``, ``Iterable`` and ``Container``. Not every subset of those three classes is a set though! Sets have the additional - property (though it is not expressed in code) that each element - occurs only once (as can be determined by iteration), and in - addition sets implement rich comparisons defined as - subclass/superclass tests. + invariant that each element occurs only once (as can be determined + by iteration), and in addition sets implement rich comparisons + defined as subclass/superclass tests. Sets with different implementations can be compared safely, efficiently and correctly. Because ``Set`` derives from @@ -255,23 +289,24 @@ immediately if two sets of unequal length are compared. Similarly, ``__le__`` returns ``False`` immediately if the first set has more members than the second set. Note that set inclusion - implements only a partial ordering; e.g. {1, 2} and {1, 3} are not - ordered (all three of ``<``, ``==`` and ``>`` return ``False`` for - these arguments). Sets cannot be ordered relative to mappings or - sequences, but they can be compared for equality (and then they - always compare unequal). - - XXX Should we also implement the ``issubset`` and ``issuperset`` - methods found on the set type in Python 2 (which are apparently - just aliases for ``__le__`` and ``__ge__``)? - - XXX Should this class also implement union, intersection, - symmetric and asymmetric difference and/or the corresponding - operators? The problem with those (unlike the comparison - operators) is what should be the type of the return value. I'm - tentatively leaving these out -- if you need them, you can test - for a ``Set`` instance that implements e.g. ``__and__``. Some - alternatives: make these abstract methods (even though the + implements only a partial ordering; e.g. ``{1, 2}`` and ``{1, 3}`` + are not ordered (all three of ``<``, ``==`` and ``>`` return + ``False`` for these arguments). Sets cannot be ordered relative + to mappings or sequences, but they can be compared for equality + (and then they always compare unequal). + + **Open issue:** Should we also implement the ``issubset`` and + ``issuperset`` methods found on the set type in Python 2? As + these are just aliases for ``__le__`` and ``__ge__``, I'm tempted + to leave these out. + + **Open issue:** Should this class also implement the operators + and/or methods that compute union, intersection, symmetric and + asymmetric difference? The problem with those (unlike the + comparison operators) is what should be the type of the return + value. I'm tentatively leaving these out -- if you need them, you + can test for a ``Set`` instance that implements e.g. ``__and__``. + Some alternatives: make these abstract methods (even though the semantics apart from the type are well-defined); or make them concrete methods that return a specific concrete set type; or make them concrete methods that assume the class constructor always @@ -299,7 +334,7 @@ ``.add(x)`` Abstract method that adds the element ``x``, if it isn't already in the set. - + ``.remove(x)`` Abstract method that removes the element ``x``; raises @@ -314,22 +349,25 @@ Abstract method that empties the set. (Making this concrete would just add a slow, cumbersome default implementation.) - XXX Should we support all the operations implemented by the Python - 2 ``set`` type? I.e. union, update, __or__, __ror__, __ior__, - intersection, intersection_update, __and__, __rand__, __iand__, - difference, difference_update, __xor__, __rxor__, __ixor__, - symmetric_difference, symmetric_difference_update, __sub__, - __rsub__, __isub__. Note that in Python 2, ``a.update(b)`` is not - exactly the same as ``a |= b``, since ``update()`` takes any - iterable for an argument, while ``|=`` requires another set; - similar for the other operators. - + **Open issue:** Should we support all the operations implemented + by the Python 2 ``set`` type? I.e. union, update, __or__, + __ror__, __ior__, intersection, intersection_update, __and__, + __rand__, __iand__, difference, difference_update, __xor__, + __rxor__, __ixor__, symmetric_difference, + symmetric_difference_update, __sub__, __rsub__, __isub__. Note + that in Python 2, ``a.update(b)`` is not exactly the same as ``a + |= b``, since ``update()`` takes any iterable for an argument, + while ``|=`` requires another set; similar for the other + operators. + Mappings '''''''' These abstract classes represent various stages of mapping-ness. +The built-in type ``dict`` derives from ``MutableMapping``. + XXX Do we need BasicMapping and IterableMapping? Perhaps we should just start with Mapping. @@ -387,6 +425,10 @@ These abstract classes represent various stages of sequence-ness. +The built-in ``list`` and ``bytes`` types derive from +``MutableSequence``. The built-in ``tuple`` and ``str`` types derive +from ``HashableSequence``. + ``Sequence`` A subclass of ``Iterable``, ``Finite``, ``Container``. It defines a new abstract method ``__getitem__`` that has a From python-checkins at python.org Thu Apr 19 21:05:18 2007 From: python-checkins at python.org (brett.cannon) Date: Thu, 19 Apr 2007 21:05:18 +0200 (CEST) Subject: [Python-checkins] r54879 - peps/trunk/pep-0352.txt Message-ID: <20070419190518.580C11E4016@bag.python.org> Author: brett.cannon Date: Thu Apr 19 21:05:14 2007 New Revision: 54879 Modified: peps/trunk/pep-0352.txt Log: Update PEP to cover the deprecation of BaseException.message in Python 2.6. Modified: peps/trunk/pep-0352.txt ============================================================================== --- peps/trunk/pep-0352.txt (original) +++ peps/trunk/pep-0352.txt Thu Apr 19 21:05:14 2007 @@ -2,8 +2,7 @@ Title: Required Superclass for Exceptions Version: $Revision$ Last-Modified: $Date$ -Author: Brett Cannon - Guido van Rossum +Author: Brett Cannon, Guido van Rossum Status: Final Type: Standards Track Content-Type: text/x-rst @@ -15,16 +14,14 @@ ======== In Python 2.4 and before, any (classic) class can be raised as an -exception. The plan is to allow new-style classes starting in Python -2.5, but this makes the problem worse -- it would mean *any* class (or -instance) can be raised! (This is not the case in the final version; -only built-in exceptions can be new-style which means you need to -inherit from a built-in exception to have user-defined exceptions also -be new-style) This is a problem because it -prevents any guarantees from being made about the interface of exceptions. +exception. The plan for 2.5 was to allow new-style classes, but this +makes the problem worse -- it would mean *any* class (or +instance) can be raised! This is a problem as it prevents any +guarantees from being made about the interface of exceptions. This PEP proposes introducing a new superclass that all raised objects must inherit from. Imposing the restriction will allow a standard -interface for exceptions to exist that can be relied upon. +interface for exceptions to exist that can be relied upon. It also +leads to a known hierarchy for all exceptions to adhere to. One might counter that requiring a specific base class for a particular interface is unPythonic. However, in the specific case of @@ -40,13 +37,13 @@ from Exception. This is a problem since this includes two exceptions (KeyboardInterrupt and SystemExit) that often need to be excepted from the application's exception handling: the default behavior of shutting -the interpreter down with resp. Without a traceback is usually more -desirable than whatever the application might do (with the possible -exception of applications that emulate Python's interactive command -loop with ``>>>`` prompt). Changing it so that these two exceptions -inherit from the common superclass instead of Exception will make it -easy for people to write ``except`` clauses that are not overreaching -and not catch exceptions that should propagate up. +the interpreter down without a traceback is usually more desirable than +whatever the application might do (with the possible exception of +applications that emulate Python's interactive command loop with +``>>>`` prompt). Changing it so that these two exceptions inherit +from the common superclass instead of Exception will make it easy for +people to write ``except`` clauses that are not overreaching and not +catch exceptions that should propagate up. This PEP is based on previous work done for PEP 348 [#pep348]_. @@ -55,8 +52,7 @@ ============================= This PEP proposes introducing a new exception named BaseException that -is a new-style class and has a single attribute, ``message`` (that -will cause the deprecation of the existing ``args`` attribute) Below +is a new-style class and has a single attribute, ``args``. Below is the code as the exception will work in Python 3.0 (how it will work in Python 2.x is covered in the `Transition Plan`_ section):: @@ -64,46 +60,36 @@ """Superclass representing the base of the exception hierarchy. - Provides a 'message' attribute that contains either the single - argument to the constructor or the empty string. This attribute - is used in the string representation for the - exception. This is so that it provides the extra details in the - traceback. - + Provides an 'args' attribute that contains all arguments passed + to the constructor. Suggested practice, though, is that only a + single string argument be passed to the constructor. + """ - def __init__(self, message=''): - """Set the 'message' attribute'""" - self.message = message + def __init__(self, *args): + """Set the 'args' attribute'""" + self.args = args def __str__(self): - """Return the str of 'message'""" - return str(self.message) + """Return the str of + ``args[0] if len(args) == 1 else args``.""" + if len(self.args) == 1: + return str(self.args[0]) + else: + return str(self.args) def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self.message)) + return "%s(*%s)" % (self.__class__.__name__, repr(self.args)) -The ``message`` attribute will contain either the first argument -passed in at instantiation of the object or the empty string if no -arguments were passed in. The attribute is meant to act as a common -location to store any message that is to be passed along -with the exception that goes beyond the location of where the exception -occurred and the exception's type. -No restriction is placed upon what may be passed in for ``message`` +No restriction is placed upon what may be passed in for ``args`` for backwards-compatibility reasons. In practice, though, only -strings should be used. This keeps the string representation of the -exception to be a useful message about the exception that is -human-readable. Including programmatic information (e.g., an error -code number) should be stored as a separate attribute in a subclass. - -The ``args`` attribute is deprecated. While allowing multiple -arguments to be passed can be helpful, it is in no way essential. It -also does not make it clear which argument is going to be represented -by the ``__str__`` method. Restricting initialization to accepting a -single argument keeps the API simple and clear. This also means -providing a ``__getitem__`` method is unneeded for exceptions and thus -will be deprecated as well. +a single string argument should be used. This keeps the string +representation of the exception to be a useful message about the +exception that is human-readable; this is why the ``__str__`` method +special-cases on length-1 ``args`` value. Including programmatic +information (e.g., an error code number) should be stored as a +separate attribute in a subclass. The ``raise`` statement will be changed to require that any object passed to it must inherit from BaseException. This will make sure @@ -183,37 +169,18 @@ """Superclass representing the base of the exception hierarchy. - Provides a 'message' attribute that contains any single argument - passed in during instantiation. If more than one argument is - passed, it is set to the empty string. It is meant to represent - any message (usually some text) that should be printed out with - the traceback. Unfortunately, for backwards-compatibility, the - 'args' attribute (discussed below) is used for printing out to - tracebacks. - - The 'args' attribute and __getitem__ method are provided for - backwards-compatibility and will be deprecated at some point. + The __getitem__ method is provided for backwards-compatibility + and will be deprecated at some point. The 'message' attribute + is also deprecated. """ def __init__(self, *args): - """Set 'message' and 'args' attribute. - - 'args' will eventually be deprecated. But it is still used - when printing out tracebacks for backwards-compatibility. - Once 'args' is removed, though, 'message' will be used instead. - - """ + """Set the 'args' attribute.""" self.args = args - self.message = args[0] if args else '' def __str__(self): - """Return the str of args[0] or args, depending on length. - - Once 'args' has been removed, 'message' will be used - exclusively for the str representation for exceptions. - - """ + """Return the str of args[0] or args, depending on length.""" return str(self.args[0] if len(self.args) <= 1 else self.args) @@ -231,6 +198,16 @@ """ return self.args[index] + def _get_message(self): + """Method for 'message' property.""" + warnings.warn("the 'message' attribute has been deprecated " + "since Python 2.6") + return self.args[0] if len(args) == 1 else '' + + message = property(_get_message) + + + Deprecation of features in Python 2.9 is optional. This is because it is not known at this time if Python 2.9 (which is slated to be the @@ -242,7 +219,7 @@ when development of that version begins to determine if they are still desired. -* Python 2.5 +* Python 2.5 [done] - all standard exceptions become new-style classes @@ -254,35 +231,56 @@ * Python 2.6 - - deprecate catching string exceptions + - deprecate catching string exceptions [done] + + - deprecate ``message`` attribute (see `Retracted Ideas`_) * Python 2.7 - deprecate raising exceptions that do not inherit from BaseException + - remove ``message`` attribute + * Python 2.8 - deprecate catching exceptions that do not inherit from BaseException * Python 2.9 - - deprecate ``args`` and ``__getitem__`` (optional) + - deprecate ``__getitem__`` (optional) * Python 3.0 - drop everything that was deprecated above: - + string exceptions (both raising and catching) + + string exceptions (both raising and catching) [done] + + + all exceptions must inherit from BaseException [done] - + all exceptions must inherit from BaseException + + drop ``__getitem__``, ``message`` - + drop ``args`` and ``__getitem__`` +Retracted Ideas +=============== -Implementation -============== +A previous version of this PEP that was implemented in Python 2.5 +included a 'message' attribute on BaseException. Its purpose was to +begin a transition to BaseException accepting only a single argument. +This was to tighten the interface and to force people to use +attributes in subclasses to carry arbitrary information with an +exception instead of cramming it all into ``args``. + +Unfortunately, while implementing the removal of the ``args`` +attribute in Python 3.0 at the PyCon 2007 sprint +[#pycon2007-sprint-email]_, it was discovered that the transition was +very painful, especially for C extension modules. It was decided that +it would be better to deprecate the ``message`` attribute in +Python 2.6 (and remove in Python 2.7 and Python 3.0) and consider a +more long-term transition strategy in Python 3.0 to remove +multiple-argument support in BaseException in preference of accepting +only a single argument. Thus the introduction of ``message`` and the +original deprecation of ``args`` has been retracted. -The initial implementation of this PEP has been checked into Python 2.5 . References ========== @@ -296,6 +294,9 @@ .. [#SF_1104669] SF patch #1104669 (new-style exceptions) http://www.python.org/sf/1104669 +.. [#pycon2007-sprint-email] python-3000 email ("How far to go with cleaning up exceptions") + http://mail.python.org/pipermail/python-3000/2007-March/005911.html + Copyright ========= From python-checkins at python.org Thu Apr 19 23:50:05 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 19 Apr 2007 23:50:05 +0200 (CEST) Subject: [Python-checkins] r54880 - peps/trunk/pep-3119.txt Message-ID: <20070419215005.54CD41E4002@bag.python.org> Author: guido.van.rossum Date: Thu Apr 19 23:49:59 2007 New Revision: 54880 Modified: peps/trunk/pep-3119.txt Log: Added some comparisons to other ideas, open issues, and more references. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Thu Apr 19 23:49:59 2007 @@ -36,6 +36,14 @@ makes a set", "what makes a mapping" and "what makes a sequence". +Acknowledgements +---------------- + +Talin wrote the Rationale below [1]_. For that alone he deserves +co-authorship. But the rest of the PEP uses "I" referring to the +first author. + + Rationale ========= @@ -195,7 +203,6 @@ it has two prescribed methods. ``Hashable`` - The base class for classes defining ``__hash__``. The ``__hash__`` method should return an ``Integer`` (see "Numbers" below). The abstract ``__hash__`` method always returns 0, which @@ -233,7 +240,7 @@ ``__contains__` method should return a ``bool``.` The abstract ``__contains__`` method returns ``False``. **Invariant:** If a class ``C`` derives from ``Container`` as well as from - ``Iterable``, ``(x in o for x in o)`` should be a generator + ``Iterable``, then ``(x in o for x in o)`` should be a generator yielding only True values for any instance ``o`` of ``C``. Note: strictly speaking, there are three variants of this method's @@ -326,7 +333,6 @@ values for different types of numbers and strings.) ``MutableSet`` - This is a subclass of ``Set`` implementing additional operations to add and remove elements. The supported methods have the semantics known from the ``set`` type in Python 2: @@ -466,17 +472,119 @@ XXX define: Number, Complex, Real, Rational, Integer. Do we have a use case for Cardinal (Integer >= 0)? Do we need Indexable (converts -to Integer using __index__). +to Integer using __index__)? Or is that just subsumed into Integer +and should we use __index__ only at the C level? Guidelines for Writing ABCs --------------------------- -XXX Use @abstractmethod and Abstract base class; define abstract -methods that could be useful as an end point when called via a super -chain; define concrete methods that are very simple permutations of -abstract methods (e.g. Mapping.get); keep abstract classes small, one -per use case instead of one per concept. +Some sugegstions: + +* Use @abstractmethod and Abstract base class. + +* Define abstract methods that could be useful as an end point when + called via a super chain. + +* Define concrete methods that are very simple permutations of + abstract methods (e.g. Mapping.get). + +* Keep abstract classes small, one per use case instead of one per + concept. + +* XXX What else? + + +ABCs vs. Alternatives +===================== + +In this section I will attempt to compare and contrast ABCs to other +approaches that have been proposed. + + +ABCs vs. Duck Typing +-------------------- + +Does the introduction of ABCs mean the end of Duck Typing? I don't +think so. Python will not require that a class derives from +``BasicMapping`` or ``Sequence`` when it defines a ``__getitem__`` +method, nor will the ``x[y]`` syntax require that ``x`` is an instance +of either ABC. You will still be able to assign any "file-like" +object to ``sys.stdout``, as long as it has a ``write`` method. + +Of course, there will be some carrots to encourage users to derive +from the appropriate base classes; these vary from default +implementations for certain functionality to an improved ability to +distinguish between mappings and sequences. But there are no sticks. +If ``hasattr(x, __len__)`` works for you, great! ABCs are intended to +solve problems that don't have a good solution at all in Python 2, +such as distinguishing between mappings and sequences. + + +ABCs vs. Generic Functions +-------------------------- + +ABCs are compatible with Generic Functions (GFs). For example, my own +Generic Functions implementation [4]_ uses the classes (types) of the +arguments as the dispatch key, allowing derived classes to override +base classes. Since (from Python's perspective) ABCs are quite +ordinary classes, using an ABC in the default implementation for a GF +can be quite appropriate. For example, if I have an overloaded +``prettyprint`` function, it would make total sense to define +pretty-printing of sets like this:: + + @prettyprint.register(Set) + def pp_set(s): + return "{" + ... + "}" # Details left as an exercise + +and implementations for specific subclasses of Set could be added +easily. + +I believe ABCs also won't present any problems for RuleDispatch, +Phillip Eby's GF implementation in PEAK [5]_. + +Of course, GF proponents might claim that GFs (and concrete, or +implementation, classes) are all you need. But even they will not +deny the usefulness of inheritance; and one can easily consider the +ABCs proposed in this PEP as optional implementation base classes; +there is no requirement that all user-defined mappings derive from +``BasicMapping``. + + +ABCs vs. Interfaces +------------------- + +ABCs are not intrinsically incompatible with Interfaces, but there is +considerable overlap. For now, I'll leave it to proponents of +Interfaces to explain why Interfaces are better. I expect that much +of the work that went into e.g. defining the various shades of +"mapping-ness" and the nomenclature could easily be adapted for a +proposal to use Interfaces instead of ABCs. + + +Open Issues +=========== + +Apart from the open issues already sprinkled through the text above, +and the "category one" issue of deciding between ABCs, GFs and +Interfaces there are some fairly large looming issues. + +* Should we strive to use ABCs for *all* areas of Python? The wiki + page for ABCs created by Bill Janssen [3]_ tries to be + comprehensive: it defines everything from Comparable and Object to + files. The current PEP tries to limit itself to three areas: ABC + support (like the ``@abstractmethod`` decorator), collections types, + and numbers. The proposed class hierarchy for new I/O described in + PEP 3116 already including de-facto ABCs; these can easily be + upgraded to use the mechanisms from the current PEP if it is + accepted. Perhaps Orderable would be a good concept to define + in the current PEP; I don't expect we need to go further. + +* Perhaps the numeric classes could be moved to a separate PEP; the + issues there don't have much in common with the issues for + collection types. + +* XXX What else? References @@ -488,6 +596,16 @@ .. [2] Incomplete implementation prototype, by GvR (http://svn.python.org/view/sandbox/trunk/abc/) +.. [3] Possible Python 3K Class Tree?, wiki page created by Bill Janssen + (http://wiki.python.org/moin/AbstractBaseClasses) + +.. [4] Generic Functions implementation, by GvR + (http://svn.python.org/view/sandbox/trunk/overload/) + +.. [5] Charming Python: Scaling a new PEAK, by David Mertz + (http://www-128.ibm.com/developerworks/library/l-cppeak2/) + + Copyright ========= From python-checkins at python.org Fri Apr 20 00:47:11 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 20 Apr 2007 00:47:11 +0200 (CEST) Subject: [Python-checkins] r54881 - peps/trunk/pep-3119.txt Message-ID: <20070419224711.D0EF41E4002@bag.python.org> Author: guido.van.rossum Date: Fri Apr 20 00:47:08 2007 New Revision: 54881 Modified: peps/trunk/pep-3119.txt Log: Fix a blatant bug in the definition of hash(). Add ComposableSet, which defines union etc. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Fri Apr 20 00:47:08 2007 @@ -208,8 +208,17 @@ below). The abstract ``__hash__`` method always returns 0, which is a valid (albeit inefficient) implementation. **Invariant:** If classes ``C1`` and ``C2`` both derive from ``Hashable``, the - invariant ``hash(o1) == hash(o2)`` must imply ``o1 == o2`` for all + condition ``o1 == o2`` must imply ``hash(o1) == hash(o2)`` for all instances ``o1`` of ``C1`` and all instances ``o2`` of ``C2``. + IOW, two objects shouldn't compare equal but have different hash + values. + + Another constraint is that hashable objects, once created, should + never change their value (as compared by ``==``) or their hash + value. If a class cannot guarantee this, it should not derive + from ``Hashable``; if it cannot guarantee this for certain + instances only, ``__hash__`` for those instances should raise an + exception. Note: being an instance of this class does not imply that an object is immutable; e.g. a tuple containing a list as a member is @@ -287,8 +296,8 @@ ``Finite``, ``Iterable`` and ``Container``. Not every subset of those three classes is a set though! Sets have the additional invariant that each element occurs only once (as can be determined - by iteration), and in addition sets implement rich comparisons - defined as subclass/superclass tests. + by iteration), and in addition sets define concrete operators that + implement rich comparisons defined as subclass/superclass tests. Sets with different implementations can be compared safely, efficiently and correctly. Because ``Set`` derives from @@ -302,29 +311,33 @@ to mappings or sequences, but they can be compared for equality (and then they always compare unequal). - **Open issue:** Should we also implement the ``issubset`` and - ``issuperset`` methods found on the set type in Python 2? As - these are just aliases for ``__le__`` and ``__ge__``, I'm tempted - to leave these out. - - **Open issue:** Should this class also implement the operators - and/or methods that compute union, intersection, symmetric and - asymmetric difference? The problem with those (unlike the - comparison operators) is what should be the type of the return - value. I'm tentatively leaving these out -- if you need them, you - can test for a ``Set`` instance that implements e.g. ``__and__``. - Some alternatives: make these abstract methods (even though the - semantics apart from the type are well-defined); or make them - concrete methods that return a specific concrete set type; or make - them concrete methods that assume the class constructor always - accepts an iterable of elements; or add a new class method that - accepts an iterable of elements and that creates a new instance. - (I originally considered a "view" alternative, but the problem is - that computing ``len(a&b)`` requires iterating over ``a`` or - ``b``, and that pretty much kills the idea.) + Note: the ``issubset`` and ``issuperset`` methods found on the set + type in Python 2 are not supported, as these are mostly just + aliases for ``__le__`` and ``__ge__``. + + **Open Issues:** Should I spell out the invariants and method + definitions? + +``ComposableSet`` + This is a subclass of ``Set`` that defines abstract operators to + compute union, intersection, symmetric and asymmetric difference, + respectively ``__or__``, ``__and__``, ``__xor__`` and ``__sub__``. + These operators should return instances of ``ComposableSet``. The + abstract implementations return no meaningful values but raise + ``NotImplementedError``; this is because any generic + implementation would have to create new instances but the ABCs + don't (and shouldn't, IMO) provide an API for creating new + instances. **Invariants:** The implementations of these operators + should ensure that the results match the mathematical definition + of set composition. + + **Open Issues:** Should I spell out the invariants? Should we + define an API for creating new instances (e.g. a class method or a + fixed constructor signature)? Should we just pick a concrete + return type (e.g. ``set``)? Should we add the ``copy`` method? ``HashableSet`` - This is a subclass of both ``Set`` and ``Hashable``. It + This is a subclass of both ``ComposableSet`` and ``Hashable``. It implements a concrete ``__hash__`` method that subclasses should not override; or if they do, the subclass should compute the same hash value. This is so that sets with different implementations @@ -332,17 +345,21 @@ as dictionary keys. (A similar constraint exists on the hash values for different types of numbers and strings.) + **Open Issues:** Should I spell out the hash algorithm? Should + there be another ABC that derives from Set and Hashable (but not + from Composable)? + ``MutableSet`` - This is a subclass of ``Set`` implementing additional operations - to add and remove elements. The supported methods have the - semantics known from the ``set`` type in Python 2: + + This is a subclass of ``ComposableSet`` implementing additional + operations to add and remove elements. The supported methods have + the semantics known from the ``set`` type in Python 2: ``.add(x)`` Abstract method that adds the element ``x``, if it isn't already in the set. ``.remove(x)`` - Abstract method that removes the element ``x``; raises ``KeyError`` if ``x`` is not in the set. @@ -355,16 +372,18 @@ Abstract method that empties the set. (Making this concrete would just add a slow, cumbersome default implementation.) - **Open issue:** Should we support all the operations implemented - by the Python 2 ``set`` type? I.e. union, update, __or__, - __ror__, __ior__, intersection, intersection_update, __and__, - __rand__, __iand__, difference, difference_update, __xor__, - __rxor__, __ixor__, symmetric_difference, - symmetric_difference_update, __sub__, __rsub__, __isub__. Note - that in Python 2, ``a.update(b)`` is not exactly the same as ``a - |= b``, since ``update()`` takes any iterable for an argument, + **Open issues:** Should we support more operations implemented by + the Python 2 ``set`` type? E.g. pop, update, __ior__, + intersection_update, __iand__, difference_update, __ixor__, + symmetric_difference_update, __isub__. Should we unify ``remove`` + and ``discard``, a la Java (which has a single method returning + a boolean indicating whether it was removed or not)? + + Note that in Python 2, ``a.update(b)`` is not exactly the same as + ``a |= b``, since ``update()`` takes any iterable for an argument, while ``|=`` requires another set; similar for the other - operators. + operators. What to do about this? Do we really want the method + explosion that comes from this distinction? Mappings From python-checkins at python.org Fri Apr 20 03:39:45 2007 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2007 03:39:45 +0200 (CEST) Subject: [Python-checkins] r54882 - peps/trunk/pep-3119.txt Message-ID: <20070420013945.5602F1E400A@bag.python.org> Author: brett.cannon Date: Fri Apr 20 03:39:43 2007 New Revision: 54882 Modified: peps/trunk/pep-3119.txt Log: Fix a markup error. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Fri Apr 20 03:39:43 2007 @@ -246,7 +246,7 @@ ``Container`` The base class for classes defining ``__contains__``. The - ``__contains__` method should return a ``bool``.` The abstract + ``__contains__`` method should return a ``bool``. The abstract ``__contains__`` method returns ``False``. **Invariant:** If a class ``C`` derives from ``Container`` as well as from ``Iterable``, then ``(x in o for x in o)`` should be a generator From python-checkins at python.org Fri Apr 20 05:29:56 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 20 Apr 2007 05:29:56 +0200 (CEST) Subject: [Python-checkins] r54883 - peps/trunk/pep-3119.txt Message-ID: <20070420032956.A2FCF1E400E@bag.python.org> Author: guido.van.rossum Date: Fri Apr 20 05:29:51 2007 New Revision: 54883 Modified: peps/trunk/pep-3119.txt Log: Turn XXX into open issues. Fix append (was listed as add). Respond to Brett's email. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Fri Apr 20 05:29:51 2007 @@ -116,8 +116,8 @@ * An "ABC support framework" which defines a metaclass, a base class, a decorator, and some helpers that make it easy to define ABCs. - This will be added as a new library module named "abc", or (perhaps) - made built-in functionality. + This will be added as a new library module named "abc", or + (probably) made built-in functionality. * Specific ABCs for containers and iterators, to be added to the collections module. @@ -166,11 +166,15 @@ a class attribute named ``__abstractmethods__``. Then the ``Abstract.__new__()`` method would raise an exception if any abstract methods exist on the class being instantiated. For details see [2]_. +(However, this would incur a significant cost upon each instantiation. +A better approach would be to do most of the work in the metaclass.) -**Open issue:** perhaps ``abstractmethod`` and +**Open issue:** Probably ``abstractmethod`` and ``AbstractInstantiationError`` should become built-ins, ``Abstract``'s functionality should be subsumed by ``object``, and ``AbstractClass``'s functionality should be merged into ``type``. +This would require a more efficient implementation of the +instantiable-test sketched above. ABCs for Containers and Iterators @@ -242,7 +246,11 @@ The abstract ``__len__`` method returns 0. **Invariant:** If a class ``C`` derives from ``Finite`` as well as from ``Iterable``, the invariant ``sum(1 for x in o) == len(o)`` should hold for any - instance ``o`` of ``C``. + instance ``o`` of ``C``. **Open issue:** ``Finite`` may be a + confusing name. Other alternatives already rejected: ``Lengthy``, + ``Sizeable`` (both too cute), ``Countable`` (the set of natural + numbers is a countable set in math). We may just have to teach + people what we mean... ``Container`` The base class for classes defining ``__contains__``. The @@ -315,7 +323,7 @@ type in Python 2 are not supported, as these are mostly just aliases for ``__le__`` and ``__ge__``. - **Open Issues:** Should I spell out the invariants and method + **Open issues:** Should I spell out the invariants and method definitions? ``ComposableSet`` @@ -331,7 +339,7 @@ should ensure that the results match the mathematical definition of set composition. - **Open Issues:** Should I spell out the invariants? Should we + **Open issues:** Should I spell out the invariants? Should we define an API for creating new instances (e.g. a class method or a fixed constructor signature)? Should we just pick a concrete return type (e.g. ``set``)? Should we add the ``copy`` method? @@ -345,7 +353,7 @@ as dictionary keys. (A similar constraint exists on the hash values for different types of numbers and strings.) - **Open Issues:** Should I spell out the hash algorithm? Should + **Open issues:** Should I spell out the hash algorithm? Should there be another ABC that derives from Set and Hashable (but not from Composable)? @@ -393,9 +401,6 @@ The built-in type ``dict`` derives from ``MutableMapping``. -XXX Do we need BasicMapping and IterableMapping? Perhaps we should -just start with Mapping. - ``BasicMapping`` A subclass of ``Container`` defining the following methods: @@ -441,9 +446,18 @@ ``MutableMapping`` A subclass of ``Mapping`` that also implements some standard mutating methods. At least ``__setitem__``, ``__delitem__``, - ``clear``, ``update``. XXX Also pop, popitem, setdefault? + ``clear``, ``update``. + +**Open Issues:** + +* What about pop, popitem, setdefault? (``MutableSequence`` does have + ``pop``. Though it's not quite the same.) + +* Do we need BasicMapping and IterableMapping? We should probably + just start with Mapping. + +* We should say something about mapping view types, too. -XXX Should probably say something about mapping view types, too. Sequences ''''''''' @@ -465,9 +479,9 @@ ``IndexError`` is raised. The length should be equal to the number of values returned by the iterator. - XXX Other candidate methods, which can all have default concrete - implementations that only depend on ``__len__`` and - ``__getitem__`` with an integer argument: __reversed__, index, + **Open issues:** Other candidate methods, which can all have + default concrete implementations that only depend on ``__len__`` + and ``__getitem__`` with an integer argument: __reversed__, index, count, __add__, __mul__, __eq__, __lt__, __le__. ``HashableSequence`` @@ -478,21 +492,23 @@ ``MutableSequence`` A subclass of ``Sequence`` adding some standard mutating methods. Abstract mutating methods: ``__setitem__`` (for integer indices as - well as slices), ``__delitem__`` (ditto), ``insert``, ``add``, + well as slices), ``__delitem__`` (ditto), ``insert``, ``append``, ``reverse``. Concrete mutating methods: ``extend``, ``pop``, ``remove``. Note: this does not define ``sort()`` -- that is only required to exist on genuine ``list`` instances. - XXX What about ``+=`` and ``*=``? + **Open issues:** What about ``+=`` and ``*=``? (Including these + in the spec would clarify that they are *required* to be + implemented as in-place modifications.) ABCs for Numbers ---------------- -XXX define: Number, Complex, Real, Rational, Integer. Do we have a -use case for Cardinal (Integer >= 0)? Do we need Indexable (converts -to Integer using __index__)? Or is that just subsumed into Integer -and should we use __index__ only at the C level? +**Open issues:** Define: Number, Complex, Real, Rational, Integer. Do +we have a use case for Cardinal (Integer >= 0)? Do we need Index +(converts to Integer using __index__)? Or is that just subsumed into +Integer and should we use __index__ only at the C level? Guidelines for Writing ABCs @@ -511,7 +527,7 @@ * Keep abstract classes small, one per use case instead of one per concept. -* XXX What else? +* What else? ABCs vs. Alternatives @@ -603,7 +619,7 @@ issues there don't have much in common with the issues for collection types. -* XXX What else? +* What else? References From python-checkins at python.org Fri Apr 20 07:20:40 2007 From: python-checkins at python.org (neal.norwitz) Date: Fri, 20 Apr 2007 07:20:40 +0200 (CEST) Subject: [Python-checkins] r54884 - python/trunk/Misc/build.sh Message-ID: <20070420052040.8FE911E400A@bag.python.org> Author: neal.norwitz Date: Fri Apr 20 07:20:38 2007 New Revision: 54884 Modified: python/trunk/Misc/build.sh Log: Add an optional address to copy the failure mails to. Detect a conflict in the only file that should have outstanding changes when this script is run. This doesn't matter on the trunk, but does when run on a branch. Trunk always has the date set to today in boilerplate.tex. Each time a release is cut with a different date, a conflict occurs. (We could copy a known good version, but then we would lose changes to this file.) Modified: python/trunk/Misc/build.sh ============================================================================== --- python/trunk/Misc/build.sh (original) +++ python/trunk/Misc/build.sh Fri Apr 20 07:20:38 2007 @@ -47,6 +47,7 @@ FAILURE_SUBJECT="Python Regression Test Failures" #FAILURE_MAILTO="YOUR_ACCOUNT at gmail.com" FAILURE_MAILTO="python-checkins at python.org" +#FAILURE_CC="optional--uncomment and set to desired address" REMOTE_SYSTEM="neal at dinsdale.python.org" REMOTE_DIR="/data/ftp.python.org/pub/docs.python.org/dev/" @@ -91,7 +92,12 @@ mail_on_failure() { if [ "$NUM_FAILURES" != "0" ]; then - mutt -s "$FAILURE_SUBJECT $1 ($NUM_FAILURES)" $FAILURE_MAILTO < $2 + dest=$FAILURE_MAILTO + # FAILURE_CC is optional. + if [ "$FAILURE_CC" != "" ]; then + dest="$dest -c $FAILURE_CC" + fi + mutt -s "$FAILURE_SUBJECT $1 ($NUM_FAILURES)" $dest < $2 fi } @@ -208,8 +214,19 @@ cd $DIR/Doc F="make-doc.out" start=`current_time` -make >& ../build/$F -err=$? +# Doc/commontex/boilerplate.tex is expected to always have an outstanding +# modification for the date. When a release is cut, a conflict occurs. +# This allows us to detect this problem and not try to build the docs +# which will definitely fail with a conflict. +CONFLICTED_FILE=commontex/boilerplate.tex +conflict_count=`grep -c "<<<" $CONFLICTED_FILE` +if [ $conflict_count != 0 ]; then + echo "Conflict detected in $CONFLICTED_FILE. Doc build skipped." > ../build/$F + err=1 +else + make >& ../build/$F + err=$? +fi update_status "Making doc" "$F" $start if [ $err != 0 ]; then NUM_FAILURES=1 From python-checkins at python.org Fri Apr 20 16:49:06 2007 From: python-checkins at python.org (lars.gustaebel) Date: Fri, 20 Apr 2007 16:49:06 +0200 (CEST) Subject: [Python-checkins] r54885 - in python/branches/release25-maint: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20070420144906.148711E4016@bag.python.org> Author: lars.gustaebel Date: Fri Apr 20 16:49:02 2007 New Revision: 54885 Modified: python/branches/release25-maint/Lib/tarfile.py python/branches/release25-maint/Lib/test/test_tarfile.py python/branches/release25-maint/Misc/NEWS Log: Fix directory names to have only one trailing slash. A regression from rev. 52525. Modified: python/branches/release25-maint/Lib/tarfile.py ============================================================================== --- python/branches/release25-maint/Lib/tarfile.py (original) +++ python/branches/release25-maint/Lib/tarfile.py Fri Apr 20 16:49:02 2007 @@ -1842,7 +1842,7 @@ tarinfo.type = DIRTYPE # Directory names should have a '/' at the end. - if tarinfo.isdir(): + if tarinfo.isdir() and not tarinfo.name.endswith("/"): tarinfo.name += "/" self.members.append(tarinfo) Modified: python/branches/release25-maint/Lib/test/test_tarfile.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_tarfile.py (original) +++ python/branches/release25-maint/Lib/test/test_tarfile.py Fri Apr 20 16:49:02 2007 @@ -191,6 +191,13 @@ except: pass + def test_dirtype(self): + for tarinfo in self.tar: + if tarinfo.isdir(): + self.assert_(tarinfo.name.endswith("/")) + self.assert_(not tarinfo.name[:-1].endswith("/")) + + class ReadStreamTest(ReadTest): sep = "|" Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Fri Apr 20 16:49:02 2007 @@ -4,6 +4,17 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 2.5.2c1? +============================= + +*Release date: XX-XXX-XXXX* + +Library +------- + +- tarfile.py: Fix directory names to have only one trailing slash. + + What's New in Python 2.5.1? ============================= From buildbot at python.org Fri Apr 20 18:34:19 2007 From: buildbot at python.org (buildbot at python.org) Date: Fri, 20 Apr 2007 16:34:19 +0000 Subject: [Python-checkins] buildbot warnings in hppa Ubuntu dapper 2.5 Message-ID: <20070420163419.521811E400A@bag.python.org> The Buildbot has detected a new failure of hppa Ubuntu dapper 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/hppa%2520Ubuntu%2520dapper%25202.5/builds/79 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: lars.gustaebel Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Fri Apr 20 19:54:40 2007 From: python-checkins at python.org (facundo.batista) Date: Fri, 20 Apr 2007 19:54:40 +0200 (CEST) Subject: [Python-checkins] r54886 - python/branches/decimal-branch Message-ID: <20070420175440.6AB9B1E400A@bag.python.org> Author: facundo.batista Date: Fri Apr 20 19:54:37 2007 New Revision: 54886 Added: python/branches/decimal-branch/ - copied from r54885, python/trunk/ Log: Creating a private branch to work on Decimal and update it to last spec. From python-checkins at python.org Fri Apr 20 20:17:19 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 20 Apr 2007 20:17:19 +0200 (CEST) Subject: [Python-checkins] r54887 - sandbox/trunk/abc/abc.py Message-ID: <20070420181719.D916D1E400A@bag.python.org> Author: guido.van.rossum Date: Fri Apr 20 20:17:18 2007 New Revision: 54887 Modified: sandbox/trunk/abc/abc.py Log: Do more of the work for abstract class detection in the metaclass. Use Finite instead of Sizeable. Modified: sandbox/trunk/abc/abc.py ============================================================================== --- sandbox/trunk/abc/abc.py (original) +++ sandbox/trunk/abc/abc.py Fri Apr 20 20:17:18 2007 @@ -17,6 +17,9 @@ import sys +### ABC SUPPORT ### + + def abstractmethod(funcobj): """A decorator indicating abstract methods. @@ -42,7 +45,7 @@ def my_abstract_class_method(self, ...): ... """ - funcobj.__abstractmethod__ = True + funcobj.__isabstractmethod__ = True return funcobj @@ -52,12 +55,14 @@ def __new__(mcls, name, bases, namespace): cls = super(AbstractClass, mcls).__new__(mcls, name, bases, namespace) - abstracts = set() + abstracts = {name + for name, value in namespace.items() + if getattr(value, "__isabstractmethod__", False)} for base in bases: - abstracts.update(getattr(base, "__abstractmethods__", set())) - for name, value in namespace.items(): - if getattr(value, "__abstractmethod__", False): - abstracts.add(name) + for name in getattr(base, "__abstractmethods__", set()): + value = getattr(cls, name, None) + if getattr(value, "__isabstractmethod__", False): + abstracts.add(name) cls.__abstractmethods__ = abstracts return cls @@ -86,11 +91,7 @@ """ def __new__(cls): - bad = set() - for name in cls.__abstractmethods__: - value = getattr(cls, name, None) - if getattr(value, "__abstractmethod__", False): - bad.add(name) + bad = cls.__abstractmethods__ if bad: raise AbstractInstantiationError(bad) return super(Abstract, cls).__new__(cls) @@ -114,7 +115,7 @@ @abstractmethod def __iter__(self): - return Iterator() + return _EmptyIterator() class Iterator(Iterable): @@ -129,30 +130,38 @@ return self -class Sizeable(Abstract): +class _EmptyIterator(Iterator): - @abstractmethod - def __len__(self): - return 0 + """Implementation detail used by Iterable.__iter__().""" + def next(self): + # This will call Iterator.next() and hence will raise StopIteration. + return super(_EmptyIterator, self).next() + # Or: return Iterator.next(self) + # Or: raise StopIteration -### SETS ### +class Finite(Abstract): -class BasicSet(Abstract): + @abstractmethod + def __len__(self): + return 0 - # XXX Alternative name: Container? Oracle (as in Delphi's Oracle)? +class Container(Abstract): - """A basic set has __contains__() and that's it.""" + """A container has a __contains__() method.""" @abstractmethod def __contains__(self, elem): return False -class IterableSet(BasicSet, Iterable): +### SETS ### + + +class BasicSet(Container, Iterable): - """An iterable set is a basic set that is also iterable. + """A basic set is an iterable container. It may not have a length though; it may be infinite! @@ -161,9 +170,9 @@ """ -class SizeableSet(IterableSet, Sizeable): +class Set(Container, Iterable, Finite): - """A sizeable set is an iterable set that has a finite, known size. + """A plain set is a finite, iterable container. This enables a generic implementation of equality and ordering based on set inclusion. @@ -175,7 +184,7 @@ """ def __le__(self, other): - if not isinstance(other, SizeableSet): + if not isinstance(other, Set): return NotImplemented if len(self) > len(other): return False @@ -185,12 +194,12 @@ return True def __lt__(self, other): - if not isinstance(other, SizeableSet): + if not isinstance(other, Set): return NotImplemented return len(self) < len(other) and self.__le__(other) def __eq__(self, other): - if not isinstance(other, SizeableSet): + if not isinstance(other, Set): return NotImplemented return len(self) == len(other) and self.__le__(other) @@ -198,7 +207,7 @@ # XXX The following implementations of &, |, ^, - return frozen sets # because we have to pick a concrete type. They are allowed to - # return any subclass of SizeableSet (but SizeableSet is not a + # return any subclass of Set (but Set is not a # concrete implementation). def __and__(self, other): @@ -222,7 +231,7 @@ return frozenset(new) -class HashableSet(SizeableSet, Hashable): +class HashableSet(Set, Hashable): def __hash__(self): """The hash value must match __eq__. @@ -231,6 +240,8 @@ regardless of how they are implemented, and regardless of the order of the elements; so there's not much freedom for __eq__ or __hash__. We just XOR the hash of the elements. + + XXX This should match frozenset_hash() in Objects/setobject.c. """ h = 0 for elem in self: @@ -238,16 +249,14 @@ return h -# class set(SizeableSet) +# class set(Set) # class frozenset(HashableSet) ### MAPPINGS ### -class BasicMapping(Abstract): - - # XXX derive from (BasicSet)? +class BasicMapping(Container): """A basic mapping has __getitem__(), __contains__() and get(). @@ -295,7 +304,7 @@ self._mapping = mapping -class KeysView(_MappingView, BasicSet): +class KeysView(_MappingView, Container): def __iter__(self): for key in self._mapping: @@ -305,7 +314,7 @@ return key in self._mapping -class ItemsView(_MappingView, BasicSet): +class ItemsView(_MappingView, Container): def __iter__(self): for key in self._mapping: @@ -325,26 +334,26 @@ class ValuesView(_MappingView): - # Note: does not derive from BasicSet, and does not implement __contains__! + # Note: does not derive from Container, does not implement __contains__! def __iter__(self): for key in self._mapping: yield self._mapping[key] -class SizeableMapping(IterableMapping, Sizeable): +class FiniteMapping(IterableMapping, Finite): def keys(self): - return SizeableKeysView(self) + return FiniteKeysView(self) def items(self): - return SizeableItemsView(self) + return FiniteItemsView(self) def values(self): - return SizeableValuesView(self) + return FiniteValuesView(self) def __eq__(self, other): - if not isinstance(other, SizeableMapping): + if not isinstance(other, FiniteMapping): return NotImplemented if len(other) != len(self): return False @@ -360,24 +369,24 @@ return True -class _SizeableMappingView(_MappingView, Sizeable): +class _FiniteMappingView(_MappingView, Finite): def __len__(self): return len(self._mapping) -class SizeableKeysView(_SizeableMappingView, KeysView, SizeableSet): +class FiniteKeysView(_FiniteMappingView, KeysView, Set): pass -class SizeableItemsView(_SizeableMappingView, ItemsView, SizeableSet): +class FiniteItemsView(_FiniteMappingView, ItemsView, Set): pass -class SizeableValuesView(_SizeableMappingView, ValuesView): +class FiniteValuesView(_FiniteMappingView, ValuesView): def __eq__(self, other): - if not (isinstance(other, Sizeable) and isinstance(other, Iterable)): + if not (isinstance(other, Finite) and isinstance(other, Iterable)): return NotImplemented if len(self) != len(other): return False @@ -453,10 +462,10 @@ stop = size return start, stop, step - -class Sequence(Sizeable, Iterable): + +class Sequence(Finite, Iterable): """A minimal sequence. @@ -591,10 +600,10 @@ return len(self.adaptee) -class AdaptToMapping(SizeableMapping): +class AdaptToMapping(FiniteMapping): def __new__(cls, adaptee): - self = SizeableMapping.__new__(cls) + self = FiniteMapping.__new__(cls) self.adaptee = adaptee return self @@ -608,10 +617,10 @@ return iter(self.adaptee) -class AdaptToSet(SizeableSet): +class AdaptToSet(Set): def __new__(cls, adaptee): - self = SizeableSet.__new__(cls) + self = Set.__new__(cls) self.adaptee = adaptee return self From python-checkins at python.org Fri Apr 20 20:32:44 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 20 Apr 2007 20:32:44 +0200 (CEST) Subject: [Python-checkins] r54888 - peps/trunk/pep-3119.txt Message-ID: <20070420183244.DEBDB1E401C@bag.python.org> Author: guido.van.rossum Date: Fri Apr 20 20:32:41 2007 New Revision: 54888 Modified: peps/trunk/pep-3119.txt Log: Choose Sized instead of Finite. Make a few more tentative decisions based on Brett's feedback. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Fri Apr 20 20:32:41 2007 @@ -240,17 +240,19 @@ ``StopIteration``. The concrete ``__iter__`` method returns ``self``. (Note: this assumes PEP 3114 is implemented.) -``Finite`` +``Sized`` The base class for classes defining ``__len__``. The ``__len__`` method should return an ``Integer`` (see "Numbers" below) >= 0. The abstract ``__len__`` method returns 0. **Invariant:** If a - class ``C`` derives from ``Finite`` as well as from ``Iterable``, + class ``C`` derives from ``Sized`` as well as from ``Iterable``, the invariant ``sum(1 for x in o) == len(o)`` should hold for any - instance ``o`` of ``C``. **Open issue:** ``Finite`` may be a - confusing name. Other alternatives already rejected: ``Lengthy``, - ``Sizeable`` (both too cute), ``Countable`` (the set of natural - numbers is a countable set in math). We may just have to teach - people what we mean... + instance ``o`` of ``C``. **Open issue:** Is ``Sized`` the best + name? Proposed alternatives already tentatively rejected: + ``Finite`` (nobody understood it), ``Lengthy``, ``Sizeable`` (both + too cute), ``Countable`` (the set of natural numbers is a + countable set in math), ``Enumerable`` (sounds like a sysnonym for + ``Iterable``), ``Dimension``, ``Extent`` (sound like numbers to + me). ``Container`` The base class for classes defining ``__contains__``. The @@ -301,7 +303,7 @@ ``Set`` This is a finite, iterable container, i.e. a subclass of - ``Finite``, ``Iterable`` and ``Container``. Not every subset of + ``Sized``, ``Iterable`` and ``Container``. Not every subset of those three classes is a set though! Sets have the additional invariant that each element occurs only once (as can be determined by iteration), and in addition sets define concrete operators that @@ -309,7 +311,7 @@ Sets with different implementations can be compared safely, efficiently and correctly. Because ``Set`` derives from - ``Finite``, ``__eq__`` takes a shortcut and returns ``False`` + ``Sized``, ``__eq__`` takes a shortcut and returns ``False`` immediately if two sets of unequal length are compared. Similarly, ``__le__`` returns ``False`` immediately if the first set has more members than the second set. Note that set inclusion @@ -380,18 +382,20 @@ Abstract method that empties the set. (Making this concrete would just add a slow, cumbersome default implementation.) - **Open issues:** Should we support more operations implemented by - the Python 2 ``set`` type? E.g. pop, update, __ior__, - intersection_update, __iand__, difference_update, __ixor__, - symmetric_difference_update, __isub__. Should we unify ``remove`` - and ``discard``, a la Java (which has a single method returning - a boolean indicating whether it was removed or not)? - - Note that in Python 2, ``a.update(b)`` is not exactly the same as - ``a |= b``, since ``update()`` takes any iterable for an argument, - while ``|=`` requires another set; similar for the other - operators. What to do about this? Do we really want the method - explosion that comes from this distinction? + ``.pop()`` + Concrete method that removes an arbitrary item. If the set is + empty, it raises ``KeyError``. The default implementation + removes the first item returned by the set's iterator. + + This also supports the in-place mutating operations ``|=``, + ``&=``, ``^=``, ``-=``. It does not support the named methods + that perform (almost) the same operations, like ``update``, even + though these don't have exactly the same rules (``update`` takes + any iterable, while ``|=`` requires a set). + + **Open issues:** Should we unify ``remove`` and ``discard``, a la + Java (which has a single method returning a boolean indicating + whether it was removed or not)? Mappings @@ -426,7 +430,7 @@ iteration never ends. ``Mapping`` - A subclass of ``IterableMapping`` and ``Finite``. It defines + A subclass of ``IterableMapping`` and ``Sized``. It defines concrete methods ``__eq__``, ``keys``, ``items``, ``values``. The lengh of such an object should equal to the number of elements returned by iterating over the object until the end of the @@ -445,18 +449,15 @@ ``MutableMapping`` A subclass of ``Mapping`` that also implements some standard - mutating methods. At least ``__setitem__``, ``__delitem__``, - ``clear``, ``update``. -**Open Issues:** - -* What about pop, popitem, setdefault? (``MutableSequence`` does have - ``pop``. Though it's not quite the same.) + mutating methods. Abstract methods include ``__setitem__``, + ``__delitem__``, ``clear``, ``update``. Concrete methods include + ``pop``, ``popitem``. Note: ``setdefault`` is *not* included. * Do we need BasicMapping and IterableMapping? We should probably just start with Mapping. -* We should say something about mapping view types, too. +* We should say more about mapping view types. Sequences @@ -469,7 +470,7 @@ from ``HashableSequence``. ``Sequence`` - A subclass of ``Iterable``, ``Finite``, ``Container``. It + A subclass of ``Iterable``, ``Sized``, ``Container``. It defines a new abstract method ``__getitem__`` that has a complicated signature: when called with an integer, it returns an element of the sequence or raises ``IndexError``; when called with @@ -494,12 +495,10 @@ Abstract mutating methods: ``__setitem__`` (for integer indices as well as slices), ``__delitem__`` (ditto), ``insert``, ``append``, ``reverse``. Concrete mutating methods: ``extend``, ``pop``, - ``remove``. Note: this does not define ``sort()`` -- that is only - required to exist on genuine ``list`` instances. - - **Open issues:** What about ``+=`` and ``*=``? (Including these - in the spec would clarify that they are *required* to be - implemented as in-place modifications.) + ``remove``. Concrete mutating operators: ``+=``, ``*=`` (these + mutate the object in place). Note: this does not define + ``sort()`` -- that is only required to exist on genuine ``list`` + instances. ABCs for Numbers From python-checkins at python.org Fri Apr 20 22:11:00 2007 From: python-checkins at python.org (lars.gustaebel) Date: Fri, 20 Apr 2007 22:11:00 +0200 (CEST) Subject: [Python-checkins] r54889 - in python/branches/release25-maint: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20070420201100.E07C91E4016@bag.python.org> Author: lars.gustaebel Date: Fri Apr 20 22:10:59 2007 New Revision: 54889 Modified: python/branches/release25-maint/Lib/tarfile.py python/branches/release25-maint/Lib/test/test_tarfile.py python/branches/release25-maint/Misc/NEWS Log: Patch #1695229: Fix a regression with tarfile.open() and a missing name argument. Modified: python/branches/release25-maint/Lib/tarfile.py ============================================================================== --- python/branches/release25-maint/Lib/tarfile.py (original) +++ python/branches/release25-maint/Lib/tarfile.py Fri Apr 20 22:10:59 2007 @@ -1044,7 +1044,9 @@ can be determined, `mode' is overridden by `fileobj's mode. `fileobj' is not closed, when TarFile is closed. """ - self.name = os.path.abspath(name) + self.name = name + if self.name is not None: + self.name = os.path.abspath(name) if len(mode) > 1 or mode not in "raw": raise ValueError("mode must be 'r', 'a' or 'w'") Modified: python/branches/release25-maint/Lib/test/test_tarfile.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_tarfile.py (original) +++ python/branches/release25-maint/Lib/test/test_tarfile.py Fri Apr 20 22:10:59 2007 @@ -633,15 +633,21 @@ self.assertEqual(tarfile.filemode(07111), '---s--s--t') class OpenFileobjTest(BaseTest): - # Test for SF bug #1496501. def test_opener(self): + # Test for SF bug #1496501. fobj = StringIO.StringIO("foo\n") try: - tarfile.open("", "r", fileobj=fobj) + tarfile.open("", mode="r", fileobj=fobj) except tarfile.ReadError: self.assertEqual(fobj.tell(), 0, "fileobj's position has moved") + def test_fileobj(self): + # Test for SF bug #1695229, opening a tarfile without + # a name argument. + tarfile.open(mode="r", fileobj=open(tarname(""))) + tarfile.TarFile(mode="r", fileobj=open(tarname(""))) + if bz2: # Bzip2 TestCases class ReadTestBzip2(ReadTestGzip): Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Fri Apr 20 22:10:59 2007 @@ -12,6 +12,9 @@ Library ------- +- Patch #1695229: Fix a regression with tarfile.open() and a missing name + argument. + - tarfile.py: Fix directory names to have only one trailing slash. From python-checkins at python.org Fri Apr 20 22:55:17 2007 From: python-checkins at python.org (andrew.kuchling) Date: Fri, 20 Apr 2007 22:55:17 +0200 (CEST) Subject: [Python-checkins] r54890 - peps/trunk/pep2pyramid.py Message-ID: <20070420205517.D85D31E4013@bag.python.org> Author: andrew.kuchling Date: Fri Apr 20 22:55:15 2007 New Revision: 54890 Modified: peps/trunk/pep2pyramid.py Log: Escape backslashes in PEPs when writing an index.yml Modified: peps/trunk/pep2pyramid.py ============================================================================== --- peps/trunk/pep2pyramid.py (original) +++ peps/trunk/pep2pyramid.py Fri Apr 20 22:55:15 2007 @@ -428,6 +428,7 @@ def write_pyramid_index(destDir, title): filename = os.path.join(destDir, 'index.yml') fp = codecs.open(filename, 'w', 'utf-8') + title = title.replace('\\', '\\\\') # Escape existing backslashes fp.write(INDEX_YML % title.replace('"', '\\"')) fp.close() os.chmod(filename, 0664) From python-checkins at python.org Fri Apr 20 23:05:48 2007 From: python-checkins at python.org (facundo.batista) Date: Fri, 20 Apr 2007 23:05:48 +0200 (CEST) Subject: [Python-checkins] r54891 - python/branches/decimal-branch/Lib/test/test_decimal.py Message-ID: <20070420210548.DFC261E400A@bag.python.org> Author: facundo.batista Date: Fri Apr 20 23:05:45 2007 New Revision: 54891 Modified: python/branches/decimal-branch/Lib/test/test_decimal.py Log: Made it a bit more debug-friendly: now, you can call it with the name of the test(s) you want to execute, and it will only execute that(those) test(s), and will *not* execute the doctests (normally, I have prints in the code, so doctests will always fail). Also, you can call it with --debug, and it will show the test number, and context, before executing each test. Modified: python/branches/decimal-branch/Lib/test/test_decimal.py ============================================================================== --- python/branches/decimal-branch/Lib/test/test_decimal.py (original) +++ python/branches/decimal-branch/Lib/test/test_decimal.py Fri Apr 20 23:05:45 2007 @@ -142,10 +142,6 @@ #print line try: t = self.eval_line(line) - except InvalidOperation: - print 'Error in test cases:' - print line - continue except DecimalException, exception: #Exception raised where there shoudn't have been one. self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line) @@ -194,7 +190,8 @@ Sides = s.split('->') L = Sides[0].strip().split() id = L[0] -# print id, + if DEBUG: + print "Test ", id, funct = L[1].lower() valstemp = L[2:] L = Sides[1].strip().split() @@ -246,7 +243,7 @@ self.context.traps[error] = 0 v = self.context.create_decimal(v) else: - v = Decimal(v) + v = Decimal(v, self.context) vals.append(v) ans = FixQuotes(ans) @@ -264,6 +261,8 @@ else: self.fail("Did not raise %s in %s" % (error, s)) self.context.traps[error] = 0 + if DEBUG: + print "--", self.context try: result = str(funct(*vals)) if fname == 'same_quantum': @@ -301,17 +300,6 @@ def change_clamp(self, clamp): self.context._clamp = clamp -# Dynamically build custom test definition for each file in the test -# directory and add the definitions to the DecimalTest class. This -# procedure insures that new files do not get skipped. -for filename in os.listdir(directory): - if '.decTest' not in filename: - continue - head, tail = filename.split('.') - tester = lambda self, f=filename: self.eval_file(directory + f) - setattr(DecimalTest, 'test_' + head, tester) - del filename, head, tail, tester - # The following classes test the behaviour of Decimal according to PEP 327 @@ -1091,7 +1079,7 @@ self.assert_(new_ctx is not set_ctx, 'did not copy the context') self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context') -def test_main(arith=False, verbose=None): +def test_main(arith=False, verbose=None, todo_tests=None, debug=None): """ Execute the tests. Runs all arithmetic tests if arith is True or if the "decimal" resource @@ -1099,35 +1087,57 @@ """ init() - global TEST_ALL + global TEST_ALL, DEBUG TEST_ALL = arith or is_resource_enabled('decimal') + DEBUG = debug + + if todo_tests is None: + test_classes = [ + DecimalExplicitConstructionTest, + DecimalImplicitConstructionTest, + DecimalArithmeticOperatorsTest, + DecimalUseOfContextTest, + DecimalUsabilityTest, + DecimalPythonAPItests, + ContextAPItests, + DecimalTest, + WithStatementTest, + ] + else: + test_classes = [DecimalTest] + + # Dynamically build custom test definition for each file in the test + # directory and add the definitions to the DecimalTest class. This + # procedure insures that new files do not get skipped. + for filename in os.listdir(directory): + if '.decTest' not in filename or filename.startswith("."): + continue + head, tail = filename.split('.') + if todo_tests is not None and head not in todo_tests: + continue + tester = lambda self, f=filename: self.eval_file(directory + f) + setattr(DecimalTest, 'test_' + head, tester) + del filename, head, tail, tester - test_classes = [ - DecimalExplicitConstructionTest, - DecimalImplicitConstructionTest, - DecimalArithmeticOperatorsTest, - DecimalUseOfContextTest, - DecimalUsabilityTest, - DecimalPythonAPItests, - ContextAPItests, - DecimalTest, - WithStatementTest, - ] try: run_unittest(*test_classes) - import decimal as DecimalModule - run_doctest(DecimalModule, verbose) + if todo_tests is None: + import decimal as DecimalModule + run_doctest(DecimalModule, verbose) finally: setcontext(ORIGINAL_CONTEXT) if __name__ == '__main__': - # Calling with no arguments runs all tests. - # Calling with "Skip" will skip over 90% of the arithmetic tests. - if len(sys.argv) == 1: - test_main(arith=True, verbose=True) - elif len(sys.argv) == 2: - arith = sys.argv[1].lower() != 'skip' - test_main(arith=arith, verbose=True) + import optparse + p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]") + p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test') + p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests') + (opt, args) = p.parse_args() + + if opt.skip: + test_main(arith=False, verbose=True) + elif args: + test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug) else: - raise ValueError("test called with wrong arguments, use test_Decimal [Skip]") + test_main(arith=True, verbose=True) From python-checkins at python.org Fri Apr 20 23:14:30 2007 From: python-checkins at python.org (facundo.batista) Date: Fri, 20 Apr 2007 23:14:30 +0200 (CEST) Subject: [Python-checkins] r54893 - python/branches/decimal-branch/Lib/decimal.py Message-ID: <20070420211430.CBE8A1E400B@bag.python.org> Author: facundo.batista Date: Fri Apr 20 23:14:29 2007 New Revision: 54893 Modified: python/branches/decimal-branch/Lib/decimal.py Log: All the operations that already existed pass ok the new tests (except power). For this, I fixed some bugs, reordered some code (without changing functionality), and made only one important change: Added a P value to the valid exponents, because we needed a different diagnostic information. So far, for diagnostic information we used the Decimal._int digits, because that was all that was needed. I think it's more clear to leave there the payload digits, and not make that structure more complex, and create the new exponent. P is from Phantom signal, because for everybody asking self._isnan(), it will return 1 (quiet NaN). But if you want to look at it in more detail, you will now that in a past life, it was signaled. Modified: python/branches/decimal-branch/Lib/decimal.py ============================================================================== --- python/branches/decimal-branch/Lib/decimal.py (original) +++ python/branches/decimal-branch/Lib/decimal.py Fri Apr 20 23:14:29 2007 @@ -204,13 +204,21 @@ x ** (non-integer) x ** (+-)INF An operand is invalid + + The result of the operation after these is a quiet positive NaN, + except when the cause is a signaling NaN, in which case the result is + also a quiet NaN, but with the original sign, and an optional + diagnostic information. """ def handle(self, context, *args): if args: if args[0] == 1: # sNaN, must drop 's' but keep diagnostics return Decimal( (args[1]._sign, args[1]._int, 'n') ) + elif args[0] == 2: + return Decimal( (args[1], args[2], 'P') ) return NaN + class ConversionSyntax(InvalidOperation): """Trying to convert badly formed string. @@ -218,9 +226,8 @@ converted to a number and it does not conform to the numeric string syntax. The result is [0,qNaN]. """ - def handle(self, context, *args): - return (0, (0,), 'n') # Passed to something which uses a tuple. + return NaN class DivisionByZero(DecimalException, ZeroDivisionError): """Division by 0. @@ -562,11 +569,11 @@ raise ValueError('Invalid sign') for digit in value[1]: if not isinstance(digit, (int,long)) or digit < 0: - raise ValueError("The second value in the tuple must be" + raise ValueError("The second value in the tuple must be " "composed of non negative integer elements.") self._sign = value[0] self._int = tuple(value[1]) - if value[2] in ('F','n','N'): + if value[2] in ('F','n','N', 'P'): self._exp = value[2] self._is_special = True else: @@ -597,9 +604,18 @@ sig, sign, diag = _isnan(value) self._is_special = True if len(diag) > context.prec: # Diagnostic info too long - self._sign, self._int, self._exp = \ - context._raise_error(ConversionSyntax) - return self + # sig=1, qNaN -> ConversionSyntax + # sig=2, sNaN -> InvalidOperation + digits = tuple(int(x) for x in diag[-context.prec:]) + if sig == 1: + self._exp = 'P' # qNaN + self._sign = sign + self._int = digits + return self + + return context._raise_error(InvalidOperation, + 'diagnostic info too long', + 2, sign, digits) if sig == 1: self._exp = 'n' # qNaN else: # sig == 2 @@ -611,8 +627,8 @@ self._sign, self._int, self._exp = _string2exact(value) except ValueError: self._is_special = True - self._sign, self._int, self._exp = \ - context._raise_error(ConversionSyntax) + return context._raise_error(ConversionSyntax, + "non parseable string") return self raise TypeError("Cannot convert %r to Decimal" % value) @@ -621,12 +637,12 @@ """Returns whether the number is not actually one. 0 if a number - 1 if NaN + 1 if NaN (it could be a normal quiet NaN or a phantom one) 2 if sNaN """ if self._is_special: exp = self._exp - if exp == 'n': + if exp == 'n' or exp == 'P': return 1 elif exp == 'N': return 2 @@ -645,7 +661,7 @@ return 1 return 0 - def _check_nans(self, other = None, context=None): + def _check_nans(self, other=None, context=None): """Returns whether the number is not actually one. if self, other are sNaN, signal @@ -999,6 +1015,9 @@ sign = min(self._sign, other._sign) if negativezero: sign = 1 + if exp < context.Etiny(): + exp = context.Etiny() + context._raise_error(Clamped) return Decimal( (sign, (0,), exp)) if not self: exp = max(exp, other._exp - context.prec-1) @@ -1217,10 +1236,11 @@ if self._isinfinity() and other._isinfinity(): if divmod: - return (context._raise_error(InvalidOperation, + reloco = (context._raise_error(InvalidOperation, '(+-)INF // (+-)INF'), context._raise_error(InvalidOperation, '(+-)INF % (+-)INF')) + return reloco return context._raise_error(InvalidOperation, '(+-)INF/(+-)INF') if self._isinfinity(): @@ -1554,6 +1574,8 @@ ans = ans._rescale(Etiny, context=context) # It isn't zero, and exp < Emin => subnormal context._raise_error(Subnormal) + if not ans: + context._raise_error(Clamped) if context.flags[Inexact]: context._raise_error(Underflow) else: @@ -1579,7 +1601,7 @@ return c return ans - def _round(self, prec=None, rounding=None, context=None): + def _round(self, prec=None, rounding=None, context=None, forceExp=None, fromQuantize=False): """Returns a rounded version of self. You can specify the precision or rounding method. Otherwise, the @@ -1625,12 +1647,19 @@ temp = Decimal(self) numdigits = len(temp._int) - if prec == numdigits: - return temp - # See if we need to extend precision +# # See if we need to extend precision expdiff = prec - numdigits - if expdiff > 0: + + # not allowing subnormal for quantize + if fromQuantize and (forceExp - context.Emax) > context.prec: + context._raise_error(InvalidOperation, "Quantize doesn't allow subnormal") + return NaN + + if expdiff >= 0: + if fromQuantize and len(temp._int)+expdiff > context.prec: + context._raise_error(InvalidOperation, 'Beyond guarded precision') + return NaN tmp = list(temp._int) tmp.extend([0] * expdiff) ans = Decimal( (temp._sign, tmp, temp._exp - expdiff)) @@ -1644,18 +1673,49 @@ context._raise_error(Rounded) return ans - # Okay, let's round and lose data - + # Okay, let's round and lose data, let's get the correct rounding function this_function = getattr(temp, self._pick_rounding_function[rounding]) - # Now we've got the rounding function + # Now we've got the rounding function + origprec = context.prec if prec != context.prec: context = context._shallow_copy() context.prec = prec ans = this_function(prec, expdiff, context) + + if forceExp is not None: + exp = forceExp + if fromQuantize and not (context.Emin <= exp <= context.Emax): + if (context.Emin <= ans._exp) and ans._int == (0,): + context._raise_error(InvalidOperation) + return NaN + + if context.Emin < exp < context.Emax: + newdiff = ans._exp - exp + if newdiff >= 0: + ans._int = ans._int + tuple([0]*newdiff) + else: + ans._int = (0,) + ans._exp = exp + else: + if not context.flags[Underflow]: + newdiff = ans._exp - exp + if newdiff >= 0: + ans._int = ans._int + tuple([0]*newdiff) + else: + ans._int = (0,) + + ans._exp = exp + context._raise_error(Rounded) + context._raise_error(Inexact, 'Changed in rounding') + return ans + + if len(ans._int) > origprec: + context._raise_error(InvalidOperation, 'Beyond guarded precision') + return NaN + context._raise_error(Rounded) context._raise_error(Inexact, 'Changed in rounding') - return ans _pick_rounding_function = {} @@ -1868,7 +1928,7 @@ context = getcontext() return context._raise_error(InvalidOperation, 'quantize with one INF') - return self._rescale(exp._exp, rounding, context, watchexp) + return self._rescale(exp._exp, rounding, context, watchexp=0, fromQuantize=True) def same_quantum(self, other): """Test whether self and other have the same exponent. @@ -1882,7 +1942,7 @@ return self._isinfinity() and other._isinfinity() and True return self._exp == other._exp - def _rescale(self, exp, rounding=None, context=None, watchexp=1): + def _rescale(self, exp, rounding=None, context=None, watchexp=1, fromQuantize=False): """Rescales so that the exponent is exp. exp = exp to scale to (an integer) @@ -1901,8 +1961,10 @@ if ans: return ans - if watchexp and (context.Emax < exp or context.Etiny() > exp): + if fromQuantize and (context.Emax < exp or context.Etiny() > exp): return context._raise_error(InvalidOperation, 'rescale(a, INF)') + if fromQuantize and exp < context.Etiny(): + return context._raise_error(InvalidOperation, '"rhs" must be no less than Etiny') if not self: ans = Decimal(self) @@ -1917,18 +1979,12 @@ return context._raise_error(InvalidOperation, 'Rescale > prec') tmp = Decimal(self) - tmp._int = (0,) + tmp._int - digits += 1 if digits < 0: tmp._exp = -digits + tmp._exp tmp._int = (0,1) digits = 1 - tmp = tmp._round(digits, rounding, context=context) - - if tmp._int[0] == 0 and len(tmp._int) > 1: - tmp._int = tmp._int[1:] - tmp._exp = exp + tmp = tmp._round(digits, rounding, context=context, forceExp=exp, fromQuantize=fromQuantize) tmp_adjusted = tmp.adjusted() if tmp and tmp_adjusted < context.Emin: @@ -2076,7 +2132,7 @@ def max(self, other, context=None): """Returns the larger value. - like max(self, other) except if one is not a number, returns + Like max(self, other) except if one is not a number, returns NaN (and signals if one is sNaN). Also rounds. """ other = _convert_other(other) @@ -2086,6 +2142,8 @@ if self._is_special or other._is_special: # If one operand is a quiet NaN and the other is number, then the # number is always returned + if other._exp == 'P': + return other sn = self._isnan() on = other._isnan() if sn or on: @@ -2844,6 +2902,8 @@ The operation is not affected by the context. """ + if a._exp == 'P': + a = self._raise_error(ConversionSyntax) return a.__str__(context=self) def to_integral(self, a): @@ -3071,7 +3131,6 @@ NaN = Decimal('NaN') - ##### crud for parsing strings ############################################# import re From python-checkins at python.org Fri Apr 20 23:24:23 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 20 Apr 2007 23:24:23 +0200 (CEST) Subject: [Python-checkins] r54894 - sandbox/trunk/abc/abc.py Message-ID: <20070420212423.DF82B1E400A@bag.python.org> Author: guido.van.rossum Date: Fri Apr 20 23:24:20 2007 New Revision: 54894 Modified: sandbox/trunk/abc/abc.py Log: Use Sized instead of Finite. Implement the instantiation check entirely in the metaclass (though still too expensive, due to extensive super usage). Modified: sandbox/trunk/abc/abc.py ============================================================================== --- sandbox/trunk/abc/abc.py (original) +++ sandbox/trunk/abc/abc.py Fri Apr 20 23:24:20 2007 @@ -64,9 +64,39 @@ if getattr(value, "__isabstractmethod__", False): abstracts.add(name) cls.__abstractmethods__ = abstracts + if abstracts: + _disable_construction(cls) return cls +def _disable_construction(cls): + """Helper to ensure that a class cannot be instantiated. + + This is done by planting a __new__ method that raises an exception + if its first argument is the cls argument to this function. + """ + # XXX This still may be too much overhead; imagine a concrete class + # deriving from a stack of ABCs, it will bounce off each ABC's + # __new__ method + # XXX Should we store the shadowed function on the class? + # XXX Is it a good idea to name the new function __new__? + dct = cls.__dict__ + shadowed_new = dct.get("__new__") + if not shadowed_new: + @staticmethod + def __new__(c, *a, **k): + if c is cls: + raise AbstractInstantiationError(cls.__abstractmethods__) + return super(cls, c).__new__(c, *a, **k) + else: + @staticmethod + def __new__(c, *a, **k): + if c is cls: + raise AbstractInstantiationError(cls.__abstractmethods__) + return shadowed_new(c, *a, **k) + cls.__new__ = __new__ + + class AbstractInstantiationError(TypeError): """Exception raised when an abstract class is instantiated.""" @@ -90,12 +120,6 @@ This implicitly sets the metaclass to AbstractClass. """ - def __new__(cls): - bad = cls.__abstractmethods__ - if bad: - raise AbstractInstantiationError(bad) - return super(Abstract, cls).__new__(cls) - ### BASICS ### @@ -141,7 +165,7 @@ # Or: raise StopIteration -class Finite(Abstract): +class Sized(Abstract): @abstractmethod def __len__(self): @@ -170,7 +194,7 @@ """ -class Set(Container, Iterable, Finite): +class Set(Container, Iterable, Sized): """A plain set is a finite, iterable container. @@ -341,19 +365,19 @@ yield self._mapping[key] -class FiniteMapping(IterableMapping, Finite): +class SizedMapping(IterableMapping, Sized): def keys(self): - return FiniteKeysView(self) + return SizedKeysView(self) def items(self): - return FiniteItemsView(self) + return SizedItemsView(self) def values(self): - return FiniteValuesView(self) + return SizedValuesView(self) def __eq__(self, other): - if not isinstance(other, FiniteMapping): + if not isinstance(other, SizedMapping): return NotImplemented if len(other) != len(self): return False @@ -369,24 +393,24 @@ return True -class _FiniteMappingView(_MappingView, Finite): +class _SizedMappingView(_MappingView, Sized): def __len__(self): return len(self._mapping) -class FiniteKeysView(_FiniteMappingView, KeysView, Set): +class SizedKeysView(_SizedMappingView, KeysView, Set): pass -class FiniteItemsView(_FiniteMappingView, ItemsView, Set): +class SizedItemsView(_SizedMappingView, ItemsView, Set): pass -class FiniteValuesView(_FiniteMappingView, ValuesView): +class SizedValuesView(_SizedMappingView, ValuesView): def __eq__(self, other): - if not (isinstance(other, Finite) and isinstance(other, Iterable)): + if not (isinstance(other, Sized) and isinstance(other, Iterable)): return NotImplemented if len(self) != len(other): return False @@ -465,7 +489,7 @@ -class Sequence(Finite, Iterable): +class Sequence(Sized, Iterable): """A minimal sequence. @@ -600,10 +624,10 @@ return len(self.adaptee) -class AdaptToMapping(FiniteMapping): +class AdaptToMapping(SizedMapping): def __new__(cls, adaptee): - self = FiniteMapping.__new__(cls) + self = SizedMapping.__new__(cls) self.adaptee = adaptee return self From python-checkins at python.org Sat Apr 21 00:26:15 2007 From: python-checkins at python.org (guido.van.rossum) Date: Sat, 21 Apr 2007 00:26:15 +0200 (CEST) Subject: [Python-checkins] r54895 - peps/trunk/pep-3119.txt Message-ID: <20070420222615.2D1561E400A@bag.python.org> Author: guido.van.rossum Date: Sat Apr 21 00:26:10 2007 New Revision: 54895 Modified: peps/trunk/pep-3119.txt Log: Work in many email responses. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Sat Apr 21 00:26:10 2007 @@ -39,9 +39,9 @@ Acknowledgements ---------------- -Talin wrote the Rationale below [1]_. For that alone he deserves -co-authorship. But the rest of the PEP uses "I" referring to the -first author. +Talin wrote the Rationale below [1]_ as well as most of the section on +ABCs vs. Interfaces. For that alone he deserves co-authorship. But +the rest of the PEP uses "I" referring to the first author. Rationale @@ -55,54 +55,58 @@ Usually this is combined with polymorphism, so that invoking a given method may run different code depending on the type of an object. -Inspection means the ability for external code (outside of the object's -methods) to examine the type or properties of that object, and make -decisions on how to treat that object based on that information. +Inspection means the ability for external code (outside of the +object's methods) to examine the type or properties of that object, +and make decisions on how to treat that object based on that +information. Both usage patterns serve the same general end, which is to be able to support the processing of diverse and potentially novel objects in a uniform way, but at the same time allowing processing decisions to be customized for each different type of object. -In classical OOP theory, invocation is the preferred usage pattern, and -inspection is actively discouraged, being considered a relic of an -earlier, procedural programming style. However, in practice this view is -simply too dogmatic and inflexible, and leads to a kind of design -rigidity that is very much at odds with the dynamic nature of a language -like Python. +In classical OOP theory, invocation is the preferred usage pattern, +and inspection is actively discouraged, being considered a relic of an +earlier, procedural programming style. However, in practice this view +is simply too dogmatic and inflexible, and leads to a kind of design +rigidity that is very much at odds with the dynamic nature of a +language like Python. In particular, there is often a need to process objects in a way that -wasn't anticipated by the creator of the object class. It is not always -the best solution to build in to every object methods that satisfy the -needs of every possible user of that object. Moreover, there are many -powerful dispatch philosophies that are in direct contrast to the -classic OOP requirement of behavior being strictly encapsulated within -an object, examples being rule or pattern-match driven logic. +wasn't anticipated by the creator of the object class. It is not +always the best solution to build in to every object methods that +satisfy the needs of every possible user of that object. Moreover, +there are many powerful dispatch philosophies that are in direct +contrast to the classic OOP requirement of behavior being strictly +encapsulated within an object, examples being rule or pattern-match +driven logic. On the the other hand, one of the criticisms of inspection by classic -OOP theorists is the lack of formalisms and the ad hoc nature of what is -being inspected. In a language such as Python, in which almost any +OOP theorists is the lack of formalisms and the ad hoc nature of what +is being inspected. In a language such as Python, in which almost any aspect of an object can be reflected and directly accessed by external code, there are many different ways to test whether an object conforms -to a particular protocol or not. For example, if asking 'is this object -a mutable sequence container?', one can look for a base class of 'list', -or one can look for a method named '__getitem__'. But note that although -these tests may seem obvious, neither of them are correct, as one -generates false negatives, and the other false positives. - -The generally agreed-upon remedy is to standardize the tests, and group -them into a formal arrangement. This is most easily done by associating -with each class a set of standard testable properties, either via the -inheritance mechanism or some other means. Each test carries with it a -set of promises: it contains a promise about the general behavior of the -class, and a promise as to what other class methods will be available. - -This PEP proposes a particular strategy for organizing these tests known -as Abstract Base Classes, or ABC. ABCs are simply Python classes that -are added into an object's inheritance tree to signal certain features -of that object to an external inspector. Tests are done using -isinstance(), and the presence of a particular ABC means that the test -has passed. +to a particular protocol or not. For example, if asking 'is this +object a mutable sequence container?', one can look for a base class +of 'list', or one can look for a method named '__getitem__'. But note +that although these tests may seem obvious, neither of them are +correct, as one generates false negatives, and the other false +positives. + +The generally agreed-upon remedy is to standardize the tests, and +group them into a formal arrangement. This is most easily done by +associating with each class a set of standard testable properties, +either via the inheritance mechanism or some other means. Each test +carries with it a set of promises: it contains a promise about the +general behavior of the class, and a promise as to what other class +methods will be available. + +This PEP proposes a particular strategy for organizing these tests +known as Abstract Base Classes, or ABC. ABCs are simply Python +classes that are added into an object's inheritance tree to signal +certain features of that object to an external inspector. Tests are +done using isinstance(), and the presence of a particular ABC means +that the test has passed. Like all other things in Python, these promises are in the nature of a gentlemen's agreement - which means that the language does not attempt @@ -203,8 +207,7 @@ '''''''''''''''' These abstract classes represent single methods like ``__iter__`` or -``__len__``. The ``Iterator`` class is included as well, even though -it has two prescribed methods. +``__len__``. ``Hashable`` The base class for classes defining ``__hash__``. The @@ -221,12 +224,12 @@ never change their value (as compared by ``==``) or their hash value. If a class cannot guarantee this, it should not derive from ``Hashable``; if it cannot guarantee this for certain - instances only, ``__hash__`` for those instances should raise an - exception. + instances only, ``__hash__`` for those instances should raise a + ``TypeError`` exception. Note: being an instance of this class does not imply that an object is immutable; e.g. a tuple containing a list as a member is - not immutable; its ``__hash__`` method raises an exception. + not immutable; its ``__hash__`` method raises ``TypeError``. ``Iterable`` The base class for classes defining ``__iter__``. The @@ -252,11 +255,11 @@ too cute), ``Countable`` (the set of natural numbers is a countable set in math), ``Enumerable`` (sounds like a sysnonym for ``Iterable``), ``Dimension``, ``Extent`` (sound like numbers to - me). + me), ``Bounded`` (probably just as confusing as ``Fininte``). ``Container`` The base class for classes defining ``__contains__``. The - ``__contains__`` method should return a ``bool``. The abstract + ``__contains__`` method should return a ``bool``. The abstract ``__contains__`` method returns ``False``. **Invariant:** If a class ``C`` derives from ``Container`` as well as from ``Iterable``, then ``(x in o for x in o)`` should be a generator @@ -272,7 +275,23 @@ of the same type as the method's target) intead of an element. For now, I'm using the same type for all three. This means that is is possible for ``x in o`` to be True even though ``x`` is - never yielded by ``iter(o)``. + never yielded by ``iter(o)``. A suggested name for the third form + is ``Searchable``. + +``PartiallyOrdered`` + This ABC defines the 4 inequality operations ``<``, ``<=``, ``>=``, + ``>``. (Note that ``==`` and ``!=`` are defined by ``object``.) + Classes deriving from this ABC should satisfy weak invariants such + as ``a < b < c`` implies ``a < c`` but don't require that for any + two instances ``x`` and ``y`` exactly one of ``x < y``, ``x == y`` + or ``x >= y`` apply. + +``TotallyOrdered`` + This ABC derives from ``PartiallyOrdered``. It adds no new + operations but implies a promise of stronger invariants. **Open + issues:** Should ``float`` derive from ``TotallyOrdered`` even + though for ``NaN`` this isn't strictly correct? + Sets @@ -302,12 +321,14 @@ out of the scope of a pragmatic proposal like this. ``Set`` - This is a finite, iterable container, i.e. a subclass of - ``Sized``, ``Iterable`` and ``Container``. Not every subset of - those three classes is a set though! Sets have the additional - invariant that each element occurs only once (as can be determined - by iteration), and in addition sets define concrete operators that - implement rich comparisons defined as subclass/superclass tests. + + This is a finite, iterable, partially ordered container, i.e. a + subclass of ``Sized``, ``Iterable``, ``Container`` and + ``PartiallyOrdered``. Not every subset of those three classes is + a set though! Sets have the additional invariant that each + element occurs only once (as can be determined by iteration), and + in addition sets define concrete operators that implement the + inequality operations as subclass/superclass tests. Sets with different implementations can be compared safely, efficiently and correctly. Because ``Set`` derives from @@ -325,8 +346,7 @@ type in Python 2 are not supported, as these are mostly just aliases for ``__le__`` and ``__ge__``. - **Open issues:** Should I spell out the invariants and method - definitions? + **Open issues:** Spell out the invariants and method definitions. ``ComposableSet`` This is a subclass of ``Set`` that defines abstract operators to @@ -360,42 +380,45 @@ from Composable)? ``MutableSet`` - This is a subclass of ``ComposableSet`` implementing additional operations to add and remove elements. The supported methods have - the semantics known from the ``set`` type in Python 2: + the semantics known from the ``set`` type in Python 2 (except + for ``discard``, which is modeled after Java): ``.add(x)`` - Abstract method that adds the element ``x``, if it isn't - already in the set. - - ``.remove(x)`` - Abstract method that removes the element ``x``; raises - ``KeyError`` if ``x`` is not in the set. + Abstract method returning a ``bool`` that adds the element + ``x`` if it isn't already in the set. It should return + ``True`` if ``x`` was added, ``False`` if it was already + there. The abstract implementation raises + ``NotImplementedError``. ``.discard(x)`` - Concrete method that removes the element ``x`` if it is - a member of the set; implemented using ``__contains__`` - and ``remove``. + Abstract method returning a ``bool`` that removes the element + ``x`` if present. It should return ``True`` if the element + was present and ``False`` if it wasn't. The abstract + implementation raises ``NotImplementedError``. ``.clear()`` - Abstract method that empties the set. (Making this concrete - would just add a slow, cumbersome default implementation.) + Abstract method that empties the set. The abstract + implementation raises ``NotImplementedError``. (Making this + concrete would just add a slow, cumbersome default + implementation.) ``.pop()`` Concrete method that removes an arbitrary item. If the set is empty, it raises ``KeyError``. The default implementation removes the first item returned by the set's iterator. + ``.toggle(x)`` + Concrete method returning a ``bool`` that adds x to the set if + it wasn't there, but removes it if it was there. It should + return ``True`` if ``x`` was added, ``False`` if it was + removed. + This also supports the in-place mutating operations ``|=``, - ``&=``, ``^=``, ``-=``. It does not support the named methods - that perform (almost) the same operations, like ``update``, even - though these don't have exactly the same rules (``update`` takes - any iterable, while ``|=`` requires a set). - - **Open issues:** Should we unify ``remove`` and ``discard``, a la - Java (which has a single method returning a boolean indicating - whether it was removed or not)? + ``&=``, ``^=``, ``-=``. These are concrete methods whose right + operand can be an arbitrary ``Iterable``. It does not support the + named methods that perform (almost) the same operations. Mappings @@ -449,16 +472,19 @@ ``MutableMapping`` A subclass of ``Mapping`` that also implements some standard - mutating methods. Abstract methods include ``__setitem__``, ``__delitem__``, ``clear``, ``update``. Concrete methods include ``pop``, ``popitem``. Note: ``setdefault`` is *not* included. +**Open issues:** + * Do we need BasicMapping and IterableMapping? We should probably just start with Mapping. * We should say more about mapping view types. +* Should we add the ``copy`` method? + Sequences ''''''''' @@ -501,13 +527,27 @@ instances. +Strings +------- + +Python 3000 has two built-in string types: byte strings (``bytes``), +deriving from ``MutableSequence``, and (Unicode) character strings +(``str``), deriving from ``HashableSequence``. + +**Open issues:** define the base interfaces for these so alternative +implementations and subclasses know what they are in for. This may be +the subject of a new PEP or PEPs (maybe PEP 358 can be co-opted for +the ``bytes`` type). + + ABCs for Numbers ---------------- -**Open issues:** Define: Number, Complex, Real, Rational, Integer. Do -we have a use case for Cardinal (Integer >= 0)? Do we need Index -(converts to Integer using __index__)? Or is that just subsumed into -Integer and should we use __index__ only at the C level? +**Open issues:** Define: ``Number``, ``Complex``, ``Real``, +``Rational``, ``Integer``. Maybe also ``Cardinal`` (``Integer`` >= +0)? We probably also need ``Index``, which converts to ``Integer`` +using ``__index__``. This should probably be moved out to a separate +PEP. Guidelines for Writing ABCs @@ -572,7 +612,7 @@ return "{" + ... + "}" # Details left as an exercise and implementations for specific subclasses of Set could be added -easily. +easily. I believe ABCs also won't present any problems for RuleDispatch, Phillip Eby's GF implementation in PEAK [5]_. @@ -595,6 +635,22 @@ "mapping-ness" and the nomenclature could easily be adapted for a proposal to use Interfaces instead of ABCs. +"Interfaces" in this context refers to a set of proposals for +additional metadata elements attached to a class which are not part of +the regular class hierarchy, but do allow for certain types of +inheritance testing. + +Such metadata would be designed, at least in some proposals, so as to +be easily mutable by an application, allowing application writers to +override the normal classification of an object. + +The drawback to this idea of attaching mutable metadata to a class is +that classes are shared state, and mutating them may lead to conflicts +of intent. Additionally, the need to override the classification of +an object can be done more cleanly using generic functions: In the +simplest case, one can define a "category membership" generic function +that simply returns False in the base implementation, and then provide +overrides that return True for any classes of interest. Open Issues =========== From python-checkins at python.org Sat Apr 21 01:06:43 2007 From: python-checkins at python.org (guido.van.rossum) Date: Sat, 21 Apr 2007 01:06:43 +0200 (CEST) Subject: [Python-checkins] r54896 - peps/trunk/pep-3119.txt Message-ID: <20070420230643.72A751E400A@bag.python.org> Author: guido.van.rossum Date: Sat Apr 21 01:06:41 2007 New Revision: 54896 Modified: peps/trunk/pep-3119.txt Log: More decisions. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Sat Apr 21 01:06:41 2007 @@ -13,8 +13,6 @@ Abstract ======== -**THIS IS A WORK IN PROGRESS! DON'T REVIEW YET!** - This is a proposal to add Abstract Base Class (ABC) support to Python 3000. It proposes: @@ -25,11 +23,6 @@ * Specific ABCs for containers and iterators, to be added to the collections module. -* Specific ABCs for numbers, to be added to a new module, yet to be - named. - -* Guidelines for writing additional ABCs. - Much of the thinking that went into the proposal is not about the specific mechanism of ABCs, as contrasted with Interfaces or Generic Functions (GFs), but about clarifying philosophical issues like "what @@ -40,8 +33,8 @@ ---------------- Talin wrote the Rationale below [1]_ as well as most of the section on -ABCs vs. Interfaces. For that alone he deserves co-authorship. But -the rest of the PEP uses "I" referring to the first author. +ABCs vs. Interfaces. For that alone he deserves co-authorship. The +rest of the PEP uses "I" referring to the first author. Rationale @@ -120,23 +113,16 @@ * An "ABC support framework" which defines a metaclass, a base class, a decorator, and some helpers that make it easy to define ABCs. - This will be added as a new library module named "abc", or - (probably) made built-in functionality. * Specific ABCs for containers and iterators, to be added to the collections module. -* Specific ABCs for numbers, to be added to a new module that is yet - to be named. - -* Guidelines for writing additional ABCs. - ABC Support Framework --------------------- -The abc module will define some utilities that help defining ABCs. -These are: +We define the following four new built-in objects that help defining +ABCs: ``@abstractmethod`` A decorator used to declare abstract methods. This should only be @@ -146,46 +132,54 @@ Such a methods may be called from the overriding method in the subclass (using ``super`` or direct invocation). +``AbstractClass`` + A metaclass to be used with classes containing abstract methods. + Classes whose metaclass is (or derives from) ``AbstractClass`` + cannot be instantiated unless all methods declared abstract using + the ``@abstractmethod`` decorator have been overridden by concrete + methods. + ``Abstract`` - A class implementing the constraint that it or its subclasses - cannot be instantiated unless each abstract method has been - overridden. Its metaclass is ``AbstractClass``. Note: being - derived from ``Abstract`` does not make a class abstract; the - abstract-ness is decided on a per-class basis, depending on - whether all methods defined with ``@abstractmethod`` have been - overridden. + An empty helper class whose metaclass is ``AbstractClass``. This + only exists as a minor convenience; deriving a class from + ``Abstract`` is the same as setting its metaclass to + ``AbstractClass``. -``AbstractClass`` - The metaclass of Abstract (and all classes derived from it). Its - purpose is to collect the information during the class - construction stage. It derives from ``type``. ``AbstractInstantiationError`` The exception raised when attempting to instantiate an abstract class. It derives from ``TypeError``. -A possible implementation would add an attribute -``__abstractmethod__`` to any method declared with -``@abstractmethod``, and add the names of all such abstract methods to -a class attribute named ``__abstractmethods__``. Then the -``Abstract.__new__()`` method would raise an exception if any abstract -methods exist on the class being instantiated. For details see [2]_. -(However, this would incur a significant cost upon each instantiation. -A better approach would be to do most of the work in the metaclass.) - -**Open issue:** Probably ``abstractmethod`` and -``AbstractInstantiationError`` should become built-ins, ``Abstract``'s -functionality should be subsumed by ``object``, and -``AbstractClass``'s functionality should be merged into ``type``. -This would require a more efficient implementation of the -instantiable-test sketched above. +**Open issues:** + +* Implementing the prohibition on instantiation may weigh down + instance creation of popular built-in classes like ``tuple`` or + ``str``. Perhaps concrete built-in classes can use a shortcut; or + perhaps there's a more efficient implementation. + +* Do we even need ``Abstract`` and ``AbstractClass``? Their + functionality can be subsumed into ``object`` and ``type``, + respectively. + +* Even if we keep them separate, ``Abstract`` is quite unnecessary + since there is hardly any difference in complexity between this:: + + class C(metaclass=AbstractClass): + @abstractmethod + def foo(self): ... + + and this:: + + class C(Abstract): + @abstractmethod + def foo(self): ... ABCs for Containers and Iterators --------------------------------- -The collections module will define ABCs necessary and sufficient to -work with sets, mappings, sequences, and some helper types such as +The ``collections`` module will define ABCs necessary and sufficient +to work with sets, mappings, sequences, and some helper types such as iterators and dictionary views. The ABCs provide implementations of their abstract methods that are @@ -200,7 +194,33 @@ Python 2 has to be implemented anew by each iterator class). No ABCs override ``__init__``, ``__new__``, ``__str__`` or -``__repr__``. +``__repr__``. Defining a standard constructor signature would +unnecessarily constrain custom container types, for example Patricia +trees or gdbm files. Defining a specific string representation for a +collection is similarly left up to individual implementations. + + +Ordering ABCs +''''''''''''' + +These ABCs are closer to ``object`` in the ABC hierarchy. + +``PartiallyOrdered`` + This ABC defines the 4 inequality operations ``<``, ``<=``, ``>=``, + ``>``. (Note that ``==`` and ``!=`` are defined by ``object``.) + Classes deriving from this ABC should satisfy weak invariants such + as ``a < b < c`` implies ``a < c`` but don't require that for any + two instances ``x`` and ``y`` exactly one of ``x < y``, ``x == y`` + or ``x >= y`` apply. + +``TotallyOrdered`` + This ABC derives from ``PartiallyOrdered``. It adds no new + operations but implies a promise of stronger invariants. **Open + issues:** Should ``float`` derive from ``TotallyOrdered`` even + though for ``NaN`` this isn't strictly correct? + +**Open issues:** Where should these live? The ``collections`` module +doesn't seem right. One Trick Ponies @@ -278,21 +298,6 @@ never yielded by ``iter(o)``. A suggested name for the third form is ``Searchable``. -``PartiallyOrdered`` - This ABC defines the 4 inequality operations ``<``, ``<=``, ``>=``, - ``>``. (Note that ``==`` and ``!=`` are defined by ``object``.) - Classes deriving from this ABC should satisfy weak invariants such - as ``a < b < c`` implies ``a < c`` but don't require that for any - two instances ``x`` and ``y`` exactly one of ``x < y``, ``x == y`` - or ``x >= y`` apply. - -``TotallyOrdered`` - This ABC derives from ``PartiallyOrdered``. It adds no new - operations but implies a promise of stronger invariants. **Open - issues:** Should ``float`` derive from ``TotallyOrdered`` even - though for ``NaN`` this isn't strictly correct? - - Sets '''' @@ -321,7 +326,6 @@ out of the scope of a pragmatic proposal like this. ``Set`` - This is a finite, iterable, partially ordered container, i.e. a subclass of ``Sized``, ``Iterable``, ``Container`` and ``PartiallyOrdered``. Not every subset of those three classes is @@ -364,7 +368,7 @@ **Open issues:** Should I spell out the invariants? Should we define an API for creating new instances (e.g. a class method or a fixed constructor signature)? Should we just pick a concrete - return type (e.g. ``set``)? Should we add the ``copy`` method? + return type (e.g. ``set``)? ``HashableSet`` This is a subclass of both ``ComposableSet`` and ``Hashable``. It @@ -444,26 +448,22 @@ Concrete method returning ``True`` if ``self[key]`` does not raise ``KeyError``, and ``False`` if it does. - -``IterableMapping`` - A subclass of ``BasicMapping`` and ``Iterable``. It defines no - new methods. Iterating over such an object should return all the - valid keys (i.e. those keys for which ``.__getitem__()`` returns a - value), once each, and nothing else. It is possible that the - iteration never ends. - ``Mapping`` - A subclass of ``IterableMapping`` and ``Sized``. It defines - concrete methods ``__eq__``, ``keys``, ``items``, ``values``. The - lengh of such an object should equal to the number of elements - returned by iterating over the object until the end of the - iterator is reached. Two mappings, even with different - implementations, can be compared for equality, and are considered - equal if and only iff their items compare equal when converted to - sets. The ``keys``, ``items`` and ``values`` methods return - views; ``keys`` and ``items`` return ``Set`` views, ``values`` - returns a ``Container`` view. The following invariant should - hold: m.items() == set(zip(m.keys(), m.values())). + A subclass of ``BasicMapping``, ``iterable`` and ``Sized``. It + defines concrete methods ``__eq__``, ``keys``, ``items``, + ``values``. Iterating over a mapping should return all the valid + keys (i.e. those keys for which ``.__getitem__()`` returns a + value), once each, and nothing else. The lengh of a mapping + should equal to the number of elements returned by iterating over + the object until the end of the iterator is reached (this is + implied by the invariant listed above for ``Sized``). Two + mappings, even with different implementations, can be compared for + equality, and are considered equal if and only iff their items + compare equal when converted to sets. The ``keys``, ``items`` and + ``values`` methods return views; ``keys`` and ``items`` return + ``Set`` views, ``values`` returns a ``Container`` view. The + following invariant should hold: m.items() == set(zip(m.keys(), + m.values())). ``HashableMapping`` A subclass of ``Mapping`` and ``Hashable``. The values should be @@ -478,13 +478,12 @@ **Open issues:** -* Do we need BasicMapping and IterableMapping? We should probably - just start with Mapping. +* Do we need both ``BasicMapping`` and ``Mapping``? We could just + start with ``Mapping``; but I believe there's some use for a + non-iterable mapping that nevertheless behaves like a basic mapping. * We should say more about mapping view types. -* Should we add the ``copy`` method? - Sequences ''''''''' @@ -553,15 +552,15 @@ Guidelines for Writing ABCs --------------------------- -Some sugegstions: +Some suggestions: -* Use @abstractmethod and Abstract base class. +* Use ``@abstractmethod`` and the ``Abstract`` base class. * Define abstract methods that could be useful as an end point when called via a super chain. * Define concrete methods that are very simple permutations of - abstract methods (e.g. Mapping.get). + abstract methods (e.g. ``Mapping.get``). * Keep abstract classes small, one per use case instead of one per concept. @@ -652,30 +651,6 @@ that simply returns False in the base implementation, and then provide overrides that return True for any classes of interest. -Open Issues -=========== - -Apart from the open issues already sprinkled through the text above, -and the "category one" issue of deciding between ABCs, GFs and -Interfaces there are some fairly large looming issues. - -* Should we strive to use ABCs for *all* areas of Python? The wiki - page for ABCs created by Bill Janssen [3]_ tries to be - comprehensive: it defines everything from Comparable and Object to - files. The current PEP tries to limit itself to three areas: ABC - support (like the ``@abstractmethod`` decorator), collections types, - and numbers. The proposed class hierarchy for new I/O described in - PEP 3116 already including de-facto ABCs; these can easily be - upgraded to use the mechanisms from the current PEP if it is - accepted. Perhaps Orderable would be a good concept to define - in the current PEP; I don't expect we need to go further. - -* Perhaps the numeric classes could be moved to a separate PEP; the - issues there don't have much in common with the issues for - collection types. - -* What else? - References ========== From python-checkins at python.org Sat Apr 21 01:54:39 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 21 Apr 2007 01:54:39 +0200 (CEST) Subject: [Python-checkins] r54897 - python/branches/bcannon-objcap/BRANCH_NOTES python/branches/bcannon-objcap/secure_python.c Message-ID: <20070420235439.2E2F81E400A@bag.python.org> Author: brett.cannon Date: Sat Apr 21 01:54:38 2007 New Revision: 54897 Added: python/branches/bcannon-objcap/secure_python.c (contents, props changed) Modified: python/branches/bcannon-objcap/BRANCH_NOTES Log: Begin a proof-of-concept app that embeds the Python interpreter in a secure fashion. Need to move changes made in Py_Initialize() over to the embedded app so that proper building of Python and all extensions can occur. Modified: python/branches/bcannon-objcap/BRANCH_NOTES ============================================================================== --- python/branches/bcannon-objcap/BRANCH_NOTES (original) +++ python/branches/bcannon-objcap/BRANCH_NOTES Sat Apr 21 01:54:38 2007 @@ -6,12 +6,15 @@ ====== Status ====== -Working on an interpreter-wide security model for Python. This is not a -replacement for rexec but should allow someone who embeds Python to be able to -execute Python code safely. +* Create app that embeds Python + + Move changes in Py_Initialize() to app. +* Remove dangerous built-ins. +* Turn on whitelisting. +* Write tests. ========== References ========== * securing_python.txt * http://docs.google.com/Doc?id=dg7fctr4_4d8tdbq +* http://www.cs.ubc.ca/~drifty/papers/python_security.pdf Added: python/branches/bcannon-objcap/secure_python.c ============================================================================== --- (empty file) +++ python/branches/bcannon-objcap/secure_python.c Sat Apr 21 01:54:38 2007 @@ -0,0 +1,17 @@ +/* + Proof-of-concept application that embeds Python with security features + turned on to prevent unmitigated access to resources. + + XXX See BRANCH_NOTES for what needs to be done. +*/ +#include "Python.h" + +int +main(int argc, char *argv[]) +{ + Py_Initialize(); + Py_Main(argc, argv); + Py_Finalize(); + + return 0; +} From python-checkins at python.org Sat Apr 21 02:08:13 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 21 Apr 2007 02:08:13 +0200 (CEST) Subject: [Python-checkins] r54898 - in python/branches/bcannon-objcap: BRANCH_NOTES Python/pythonrun.c secure_python.c Message-ID: <20070421000813.D5E011E400A@bag.python.org> Author: brett.cannon Date: Sat Apr 21 02:08:10 2007 New Revision: 54898 Modified: python/branches/bcannon-objcap/BRANCH_NOTES python/branches/bcannon-objcap/Python/pythonrun.c python/branches/bcannon-objcap/secure_python.c Log: Move changes to Py_Initialize() over to proof-of-concept app wholesale. Modified: python/branches/bcannon-objcap/BRANCH_NOTES ============================================================================== --- python/branches/bcannon-objcap/BRANCH_NOTES (original) +++ python/branches/bcannon-objcap/BRANCH_NOTES Sat Apr 21 02:08:10 2007 @@ -6,8 +6,6 @@ ====== Status ====== -* Create app that embeds Python - + Move changes in Py_Initialize() to app. * Remove dangerous built-ins. * Turn on whitelisting. * Write tests. Modified: python/branches/bcannon-objcap/Python/pythonrun.c ============================================================================== --- python/branches/bcannon-objcap/Python/pythonrun.c (original) +++ python/branches/bcannon-objcap/Python/pythonrun.c Sat Apr 21 02:08:10 2007 @@ -331,94 +331,7 @@ void Py_Initialize(void) { - PyInterpreterState *interp; - Py_ssize_t module_count, x; - PyObject *module_names_list; - PyObject *hidden_modules; - PyObject *import_module; - PyObject *import_callable; - Py_InitializeEx(1); - - interp = PyThreadState_GET()->interp; - - import_module = PyImport_ImportModule("importlib"); - - import_callable = PyObject_CallMethod(import_module, "Import", ""); - - /* Store import machinery somewhere so that a reference is held as - needed. */ - PyDict_SetItemString(interp->sysdict, "import_", import_callable); - PyDict_SetItemString(interp->builtins, "__import__", - PyDict_GetItemString(interp->sysdict, - "import_delegate")); - - Py_DECREF(import_module); - Py_DECREF(import_callable); - - /* Clear out sys.modules. - Some modules must be kept around in order for Python to function - properly. - - * __builtin__ - Lose this and Python will not run. - * __main__ - Current scope of execution. - * exceptions - Safe to keep around. - * encodings - Does dynamic import of encodings which requires globals() to - work; globals() fails when the module has been deleted. Also - fails if you hide module because importing of submodules for - encodings no longer has the parent package. - * codecs - Incremental codecs fail. - * _codecs - Exposed by codecs. - * warnings (cache in C code) - Warnings reset otherwise. Requires 'sys' module to work. - - All other modules are kept in the '.hidden' dict in sys.modules for - use by importlib. - */ - /* Get the 'warnings' module cached away at the C level. */ - PyModule_GetWarningsModule(); - module_names_list = PyDict_Keys(interp->modules); - module_count = PyList_GET_SIZE(module_names_list); - hidden_modules = PyDict_New(); - for (x=0; x < module_count; x+=1) { - char *module_name = - PyString_AS_STRING( - PyList_GET_ITEM(module_names_list, x)); - /* Modules that *must* stay visible. */ - if ((strcmp(module_name, "__builtin__") == 0) || - (strcmp(module_name, "__main__") == 0) || - (strcmp(module_name, "exceptions") == 0) || - (strcmp(module_name, "encodings") == 0) || - (strcmp(module_name, "codecs") == 0) || - (strcmp(module_name, "_codecs") == 0)) { - continue; - } - /* All other modules must be stored away for importlib. */ - else { - PyObject *module = - PyDict_GetItemString(interp->modules, - module_name); - PyDict_SetItemString(hidden_modules, module_name, - module); - PyDict_DelItemString(interp->modules, module_name); - } - } - /* Store away modules that must stick around but should not be exposed; - this is done for importlib's benefit. - */ - PyDict_SetItemString(interp->modules, ".hidden", hidden_modules); - - PyDict_SetItemString(interp->sysdict, "modules", interp->modules); - - /* Clear out sys.path_importer_cache. */ - PyDict_Clear(PyDict_GetItemString(interp->sysdict, - "path_importer_cache")); } Modified: python/branches/bcannon-objcap/secure_python.c ============================================================================== --- python/branches/bcannon-objcap/secure_python.c (original) +++ python/branches/bcannon-objcap/secure_python.c Sat Apr 21 02:08:10 2007 @@ -9,9 +9,103 @@ int main(int argc, char *argv[]) { + int return_val; + PyInterpreterState *interp; + Py_ssize_t module_count, x; + PyObject *module_names_list; + PyObject *hidden_modules; + PyObject *import_module; + PyObject *import_callable; + + /* Initialize interpreter. */ Py_Initialize(); - Py_Main(argc, argv); + + + /* Secure it. */ + interp = PyThreadState_GET()->interp; + + import_module = PyImport_ImportModule("importlib"); + + import_callable = PyObject_CallMethod(import_module, "Import", ""); + + /* Store import machinery somewhere so that a reference is held as + needed. */ + PyDict_SetItemString(interp->sysdict, "import_", import_callable); + PyDict_SetItemString(interp->builtins, "__import__", + PyDict_GetItemString(interp->sysdict, + "import_delegate")); + + Py_DECREF(import_module); + Py_DECREF(import_callable); + + /* Clear out sys.modules. + Some modules must be kept around in order for Python to function + properly. + + * __builtin__ + Lose this and Python will not run. + * __main__ + Current scope of execution. + * exceptions + Safe to keep around. + * encodings + Does dynamic import of encodings which requires globals() to + work; globals() fails when the module has been deleted. Also + fails if you hide module because importing of submodules for + encodings no longer has the parent package. + * codecs + Incremental codecs fail. + * _codecs + Exposed by codecs. + * warnings (cache in C code) + Warnings reset otherwise. Requires 'sys' module to work. + + All other modules are kept in the '.hidden' dict in sys.modules for + use by importlib. + */ + /* Get the 'warnings' module cached away at the C level. */ + PyModule_GetWarningsModule(); + module_names_list = PyDict_Keys(interp->modules); + module_count = PyList_GET_SIZE(module_names_list); + hidden_modules = PyDict_New(); + for (x=0; x < module_count; x+=1) { + char *module_name = + PyString_AS_STRING( + PyList_GET_ITEM(module_names_list, x)); + /* Modules that *must* stay visible. */ + if ((strcmp(module_name, "__builtin__") == 0) || + (strcmp(module_name, "__main__") == 0) || + (strcmp(module_name, "exceptions") == 0) || + (strcmp(module_name, "encodings") == 0) || + (strcmp(module_name, "codecs") == 0) || + (strcmp(module_name, "_codecs") == 0)) { + continue; + } + /* All other modules must be stored away for importlib. */ + else { + PyObject *module = + PyDict_GetItemString(interp->modules, + module_name); + PyDict_SetItemString(hidden_modules, module_name, + module); + PyDict_DelItemString(interp->modules, module_name); + } + } + /* Store away modules that must stick around but should not be exposed; + this is done for importlib's benefit. + */ + PyDict_SetItemString(interp->modules, ".hidden", hidden_modules); + + PyDict_SetItemString(interp->sysdict, "modules", interp->modules); + + /* Clear out sys.path_importer_cache. */ + PyDict_Clear(PyDict_GetItemString(interp->sysdict, + "path_importer_cache")); + + /* Use interpreter. */ + return_val = Py_Main(argc, argv); + /* Tear down interpreter. */ Py_Finalize(); - return 0; + return return_val; } From python-checkins at python.org Sat Apr 21 02:12:42 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 21 Apr 2007 02:12:42 +0200 (CEST) Subject: [Python-checkins] r54899 - python/branches/bcannon-objcap/BRANCH_NOTES python/branches/bcannon-objcap/build_secure_py.sh Message-ID: <20070421001242.1FFC41E400B@bag.python.org> Author: brett.cannon Date: Sat Apr 21 02:12:40 2007 New Revision: 54899 Added: python/branches/bcannon-objcap/build_secure_py.sh (contents, props changed) Modified: python/branches/bcannon-objcap/BRANCH_NOTES Log: Add simple shell script for building proof-of-concept app. Modified: python/branches/bcannon-objcap/BRANCH_NOTES ============================================================================== --- python/branches/bcannon-objcap/BRANCH_NOTES (original) +++ python/branches/bcannon-objcap/BRANCH_NOTES Sat Apr 21 02:12:40 2007 @@ -3,6 +3,12 @@ ======= Attempt to develop some form of security model for Python. +===== +Usage +===== +1. Build Python as normal. +2. Run ``build_secure_py.sh`` to build ``secure_python.exe``. + ====== Status ====== Added: python/branches/bcannon-objcap/build_secure_py.sh ============================================================================== --- (empty file) +++ python/branches/bcannon-objcap/build_secure_py.sh Sat Apr 21 02:12:40 2007 @@ -0,0 +1,2 @@ +gcc -c -IInclude -I. secure_python.c +gcc -o secure_python.exe secure_python.o libpython2.6.a From python-checkins at python.org Sat Apr 21 02:24:07 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 21 Apr 2007 02:24:07 +0200 (CEST) Subject: [Python-checkins] r54900 - in python/branches/bcannon-objcap: Modules/interpretermodule.c interpretermodule.c Message-ID: <20070421002407.D36C41E400A@bag.python.org> Author: brett.cannon Date: Sat Apr 21 02:24:04 2007 New Revision: 54900 Added: python/branches/bcannon-objcap/interpretermodule.c - copied unchanged from r54895, python/branches/bcannon-objcap/Modules/interpretermodule.c Removed: python/branches/bcannon-objcap/Modules/interpretermodule.c Log: Move interpreter module as it currently does not build and is not needed. Deleted: /python/branches/bcannon-objcap/Modules/interpretermodule.c ============================================================================== --- /python/branches/bcannon-objcap/Modules/interpretermodule.c Sat Apr 21 02:24:04 2007 +++ (empty file) @@ -1,376 +0,0 @@ -#include "Python.h" -#include "interpreter.h" -#include "cStringIO.h" - -static struct PycStringIO_CAPI* PycStringIO = NULL; - -#define PyInterpreter_GET_INTERP(interp) \ - (((PyInterpreterObject *)interp)->istate) - -/* - Destroy the interpreter and dealloc memory. -*/ -static void -interpreter_dealloc(PyObject *self) -{ - PyThreadState *new_tstate = NULL; - PyThreadState *cur_tstate = NULL; - - /* To destory an interpreter using Py_EndInterpreter() it must be the - currently running interpreter. This means you must temporariy make the - created interpreter the running interpreter again, destroy it, and then - swap back to the interpreter that created the interpreter in the first - place. */ - new_tstate = ((PyInterpreterObject *)self)->tstate; - cur_tstate = PyThreadState_Swap(new_tstate); - - Py_EndInterpreter(new_tstate); - PyEval_RestoreThread(cur_tstate); - - self->ob_type->tp_free(self); -} - -/* - Create a new interpreter. -*/ -static PyObject * -interpreter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyInterpreterObject *self; - PyThreadState *cur_tstate; - - self = (PyInterpreterObject *)type->tp_alloc(type, 0); - if (self == NULL) - return NULL; - - /* Creating a new interpreter swaps out the current one. */ - cur_tstate = PyThreadState_GET(); - - if (Py_NewInterpreter() == NULL) { - Py_DECREF(self); - /* XXX Exception best exception to use here? */ - PyErr_SetString(PyExc_Exception, "sub-interpreter creation failed"); - return NULL; - } - - self->tstate = PyThreadState_Swap(cur_tstate); - if (self->tstate == NULL) { - Py_DECREF(self); - PyErr_SetString(PyExc_Exception, "sub-interpreter swap failed"); - return NULL; - } - self->istate = (self->tstate)->interp; - - return (PyObject *)self; -} - -/* - Getter for 'builtins'. - - There is not setter because the creation of a new interpreter automatically - creates the initial execution frame which caches the built-in namespace. - */ -static PyObject * -interpreter_builtins(PyObject *self) -{ - PyObject *builtins = PyInterpreter_GET_INTERP(self)->builtins; - - Py_INCREF(builtins); - return builtins; -} - -/* - Getter for 'sys_dict'. - - There is no setter because the dict gets cached somewhere. - */ -static PyObject * -interpreter_sys_dict(PyObject *self) -{ - PyObject *sys_dict = PyInterpreter_GET_INTERP(self)->sysdict; - - Py_INCREF(sys_dict); - return sys_dict; -} - -/* - Execute Python source code in the interpreter. -*/ -static PyObject * -interpreter_exec(PyInterpreterObject *self, PyObject *arg) -{ - const char *str_arg = NULL; - PyThreadState* cur_tstate = NULL; - PyObject *main_module = NULL; - PyObject *main_dict = NULL; - PyObject *result = NULL; - const char *exc_name = NULL; - - if (!PyString_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "argument must be a string"); - return NULL; - } - - str_arg = PyString_AsString(arg); - if (!str_arg) - return NULL; - - /* Execute in 'self'. */ - cur_tstate = PyThreadState_Swap(self->tstate); - - /* If a previous exception was present, clear it out. */ - if (PyErr_Occurred()) - PyErr_Clear(); - - /* Code borrowed from PyRun_SimpleStringFlags(). */ - main_module = PyImport_AddModule("__main__"); - if (!main_module) { - goto back_to_caller; - } - - main_dict = PyModule_GetDict(main_module); - - result = PyRun_String(str_arg, Py_file_input, main_dict, main_dict); - - if (result) { - Py_DECREF(result); - } - else { - exc_name = ((PyTypeObject *)PyErr_Occurred())->tp_name; - } - - back_to_caller: - /* Execute in calling interpreter. */ - PyThreadState_Swap(cur_tstate); - - if (!result) { - PyErr_Format(PyExc_RuntimeError, - "execution raised during execution (%s)", exc_name); - return NULL; - } - - Py_RETURN_NONE; -} - -static PyObject * -redirect_output(PyObject *self, PyObject *args) -{ - PyObject *py_stdout = NULL; - PyObject *py_stderr = NULL; - PyObject *used_stdout_stderr = NULL; - - if (!PyArg_ParseTuple(args, "|OO", &py_stdout, &py_stderr)) - return NULL; - - if (!py_stdout) { - /* Argument for NewOutput() copied from PycStringIO->NewInput(). */ - py_stdout = (PycStringIO->NewOutput)(512); - if (!py_stdout) - return NULL; - } - - if (!py_stderr) { - /* Argument for NewOutput() copied from PycStringIO->NewInput(). */ - py_stderr = (PycStringIO->NewOutput)(512); - if (!py_stderr) - return NULL; - } - - used_stdout_stderr = PyTuple_New(2); - if (!used_stdout_stderr) - return NULL; - - if (PyDict_SetItemString(PyInterpreter_GET_INTERP(self)->sysdict, "stdout", - py_stdout) < 0) - return NULL; - if (PyDict_SetItemString(PyInterpreter_GET_INTERP(self)->sysdict, "stderr", - py_stderr) < 0) - return NULL; - - Py_INCREF(py_stdout); - Py_INCREF(py_stderr); - PyTuple_SET_ITEM(used_stdout_stderr, 0, py_stdout); - PyTuple_SET_ITEM(used_stdout_stderr, 1, py_stderr); - - return used_stdout_stderr; -} - -static PyObject * -exc_matches(PyInterpreterObject *self, PyObject *arg) -{ - PyThreadState *starting_tstate = NULL; - PyObject *raised_exc = NULL; - int result = 0; - - /* Can only compare against exception classes or instances. */ - if (!(PyExceptionClass_Check(arg) || PyExceptionInstance_Check(arg))) { - PyErr_SetString(PyExc_TypeError, - "argument must be an exception class or instance"); - return NULL; - } - - /* Now executing under 'self'. */ - starting_tstate = PyThreadState_Swap(self->tstate); - - raised_exc = PyErr_Occurred(); - - if (!raised_exc) { - /* Executing under calling interpreter. */ - PyThreadState_Swap(starting_tstate); - PyErr_SetString(PyExc_LookupError, "no exception set"); - return NULL; - } - - if (PyErr_GivenExceptionMatches(raised_exc, arg)) - result = 1; - - /* Execute under calling interpreter. */ - PyThreadState_Swap(starting_tstate); - - if (result) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -static PyMethodDef interpreter_methods[] = { - {"builtins", (PyCFunction)interpreter_builtins, METH_NOARGS, - "Return the built-in namespace dict."}, - {"sys_dict", (PyCFunction)interpreter_sys_dict, METH_NOARGS, - "Return the 'sys' module's data dictionary."}, - {"execute", (PyCFunction)interpreter_exec, METH_O, - "Execute the passed-in string in the interpreter."}, - {"redirect_output", (PyCFunction)redirect_output, METH_VARARGS, - "Redirect stdout to stderr. Returns tuple of objects used."}, - {"exc_matches", (PyCFunction)exc_matches, METH_O, - "Check if the raised exception in the interpreter matches the argument"}, - {NULL} -}; - - -/* - Getter for 'modules'. -*/ -static PyObject * -interpreter_get_modules(PyObject *self, void *optional) -{ - PyObject *modules = PyInterpreter_GET_INTERP(self)->modules; - - Py_INCREF(modules); - return modules; -} - -/* - Setter for 'modules'. - - Assumes no one has stored away a reference to sys.modules . Since sys.modules - is set during interpreter creation, its reference is not updated unless done so - explicitly. - - One option would have been to take the approach of builtins(), which is to have - a function that returns the initial dict and thus prevent complete dict - replacement. But since assigning to sys.modules directly has not effect, - assuming people would treat sys.modules as something to not store away seemed - reasonable. -*/ -static int -interpreter_set_modules(PyObject *self, PyObject *arg, void *optional) -{ - PyObject *old_modules = PyInterpreter_GET_INTERP(self)->modules; - - if (!PyDict_CheckExact(arg)) { - PyErr_SetString(PyExc_TypeError, - "'modules' must be set to a dict"); - return -1; - } - - Py_INCREF(arg); - Py_DECREF(old_modules); - PyInterpreter_GET_INTERP(self)->modules = arg; - PyDict_SetItemString(PyInterpreter_GET_INTERP(self)->sysdict, - "modules", arg); - - return 0; -} - - -static PyGetSetDef interpreter_getset[] = { - {"modules", interpreter_get_modules, interpreter_set_modules, - "The dict used for sys.modules.", NULL}, - {NULL} -}; - - -PyDoc_STRVAR(interpreter_type_doc, -"XXX\n\ -\n\ -XXX"); - -static PyTypeObject PyInterpreter_Type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "interpreterInterpreter", /* tp_name */ - sizeof(PyInterpreterObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - interpreter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - interpreter_type_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - interpreter_methods, /* tp_methods */ - 0, /* tp_members */ - interpreter_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - interpreter_new, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ -}; - - -PyMODINIT_FUNC -initinterpreter(void) -{ - PyObject *module; - - module = Py_InitModule3("interpreter", NULL, - "Create other Python interpreters to execute code within."); - if (module == NULL) - return; - - Py_INCREF(&PyInterpreter_Type); - if (PyType_Ready(&PyInterpreter_Type) < 0) - return; - - if (PyModule_AddObject(module, "Interpreter", - (PyObject *)&PyInterpreter_Type) < 0) - return; - - PycString_IMPORT; - if (!PycStringIO) - return; -} From python-checkins at python.org Sat Apr 21 02:26:27 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 21 Apr 2007 02:26:27 +0200 (CEST) Subject: [Python-checkins] r54901 - python/branches/bcannon-objcap Message-ID: <20070421002627.871F81E400F@bag.python.org> Author: brett.cannon Date: Sat Apr 21 02:26:26 2007 New Revision: 54901 Modified: python/branches/bcannon-objcap/ (props changed) Log: Ignore secure_python.exe . From python-checkins at python.org Sat Apr 21 09:22:58 2007 From: python-checkins at python.org (georg.brandl) Date: Sat, 21 Apr 2007 09:22:58 +0200 (CEST) Subject: [Python-checkins] r54902 - python/branches/release25-maint/Objects/exceptions.c python/branches/release25-maint/Objects/longobject.c Message-ID: <20070421072258.426991E4003@bag.python.org> Author: georg.brandl Date: Sat Apr 21 09:22:57 2007 New Revision: 54902 Modified: python/branches/release25-maint/Objects/exceptions.c python/branches/release25-maint/Objects/longobject.c Log: Backport r54757 - missing NULL checks. Modified: python/branches/release25-maint/Objects/exceptions.c ============================================================================== --- python/branches/release25-maint/Objects/exceptions.c (original) +++ python/branches/release25-maint/Objects/exceptions.c Sat Apr 21 09:22:57 2007 @@ -33,6 +33,8 @@ PyBaseExceptionObject *self; self = (PyBaseExceptionObject *)type->tp_alloc(type, 0); + if (!self) + return NULL; /* the dict is created on the fly in PyObject_GenericSetAttr */ self->message = self->dict = NULL; Modified: python/branches/release25-maint/Objects/longobject.c ============================================================================== --- python/branches/release25-maint/Objects/longobject.c (original) +++ python/branches/release25-maint/Objects/longobject.c Sat Apr 21 09:22:57 2007 @@ -1739,6 +1739,8 @@ a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) { /* |a| < |b|. */ *pdiv = _PyLong_New(0); + if (*pdiv == NULL) + return -1; Py_INCREF(a); *prem = (PyLongObject *) a; return 0; @@ -1749,6 +1751,10 @@ if (z == NULL) return -1; *prem = (PyLongObject *) PyLong_FromLong((long)rem); + if (*prem == NULL) { + Py_DECREF(z); + return -1; + } } else { z = x_divrem(a, b, prem); @@ -3204,6 +3210,8 @@ { if (PyInt_Check(*pw)) { *pw = PyLong_FromLong(PyInt_AS_LONG(*pw)); + if (*pw == NULL) + return -1; Py_INCREF(*pv); return 0; } From python-checkins at python.org Sat Apr 21 09:23:37 2007 From: python-checkins at python.org (georg.brandl) Date: Sat, 21 Apr 2007 09:23:37 +0200 (CEST) Subject: [Python-checkins] r54903 - python/branches/release25-maint/Lib/Bastion.py python/branches/release25-maint/Lib/rexec.py Message-ID: <20070421072337.639111E4003@bag.python.org> Author: georg.brandl Date: Sat Apr 21 09:23:36 2007 New Revision: 54903 Modified: python/branches/release25-maint/Lib/Bastion.py python/branches/release25-maint/Lib/rexec.py Log: Backport r54787 - better error messages in rexec and bastion Modified: python/branches/release25-maint/Lib/Bastion.py ============================================================================== --- python/branches/release25-maint/Lib/Bastion.py (original) +++ python/branches/release25-maint/Lib/Bastion.py Sat Apr 21 09:23:36 2007 @@ -97,7 +97,7 @@ """ - raise RuntimeError, "This code is not secure in Python 2.2 and 2.3" + raise RuntimeError, "This code is not secure in Python 2.2 and later" # Note: we define *two* ad-hoc functions here, get1 and get2. # Both are intended to be called in the same way: get(name). Modified: python/branches/release25-maint/Lib/rexec.py ============================================================================== --- python/branches/release25-maint/Lib/rexec.py (original) +++ python/branches/release25-maint/Lib/rexec.py Sat Apr 21 09:23:36 2007 @@ -181,7 +181,7 @@ """ - raise RuntimeError, "This code is not secure in Python 2.2 and 2.3" + raise RuntimeError, "This code is not secure in Python 2.2 and later" ihooks._Verbose.__init__(self, verbose) # XXX There's a circular reference here: From python-checkins at python.org Sat Apr 21 09:25:40 2007 From: python-checkins at python.org (georg.brandl) Date: Sat, 21 Apr 2007 09:25:40 +0200 (CEST) Subject: [Python-checkins] r54904 - in python/branches/release25-maint/Doc: api/init.tex inst/inst.tex mac/using.tex Message-ID: <20070421072540.601381E4003@bag.python.org> Author: georg.brandl Date: Sat Apr 21 09:25:39 2007 New Revision: 54904 Modified: python/branches/release25-maint/Doc/api/init.tex python/branches/release25-maint/Doc/inst/inst.tex python/branches/release25-maint/Doc/mac/using.tex Log: Backport r54763: repair missing spaces after \UNIX. Modified: python/branches/release25-maint/Doc/api/init.tex ============================================================================== --- python/branches/release25-maint/Doc/api/init.tex (original) +++ python/branches/release25-maint/Doc/api/init.tex Sat Apr 21 09:25:39 2007 @@ -245,7 +245,7 @@ program name (set by \cfunction{Py_SetProgramName()} above) and some environment variables. The returned string consists of a series of directory names separated by a platform dependent delimiter - character. The delimiter character is \character{:} on \UNIX and Mac OS X, + character. The delimiter character is \character{:} on \UNIX{} and Mac OS X, \character{;} on Windows. The returned string points into static storage; the caller should not modify its value. The value is available to Python code as the list Modified: python/branches/release25-maint/Doc/inst/inst.tex ============================================================================== --- python/branches/release25-maint/Doc/inst/inst.tex (original) +++ python/branches/release25-maint/Doc/inst/inst.tex Sat Apr 21 09:25:39 2007 @@ -296,7 +296,7 @@ \filevar{prefix} and \filevar{exec-prefix} stand for the directories that Python is installed to, and where it finds its libraries at run-time. They are always the same under Windows, and very -often the same under \UNIX and Mac OS X. You can find out what your Python +often the same under \UNIX{} and Mac OS X. You can find out what your Python installation uses for \filevar{prefix} and \filevar{exec-prefix} by running Python in interactive mode and typing a few simple commands. Under \UNIX, just type \code{python} at the shell prompt. Under Modified: python/branches/release25-maint/Doc/mac/using.tex ============================================================================== --- python/branches/release25-maint/Doc/mac/using.tex (original) +++ python/branches/release25-maint/Doc/mac/using.tex Sat Apr 21 09:25:39 2007 @@ -2,7 +2,7 @@ \sectionauthor{Bob Savage}{bobsavage at mac.com} Python on a Macintosh running Mac OS X is in principle very similar to -Python on any other \UNIX platform, but there are a number of additional +Python on any other \UNIX{} platform, but there are a number of additional features such as the IDE and the Package Manager that are worth pointing out. Python on Mac OS 9 or earlier can be quite different from Python on From python-checkins at python.org Sat Apr 21 09:28:28 2007 From: python-checkins at python.org (georg.brandl) Date: Sat, 21 Apr 2007 09:28:28 +0200 (CEST) Subject: [Python-checkins] r54905 - python/branches/release25-maint/Lib/cgitb.py Message-ID: <20070421072828.B8BC41E4003@bag.python.org> Author: georg.brandl Date: Sat Apr 21 09:28:26 2007 New Revision: 54905 Modified: python/branches/release25-maint/Lib/cgitb.py Log: Backport r54762: exceptions are no longer old-style instances. Modified: python/branches/release25-maint/Lib/cgitb.py ============================================================================== --- python/branches/release25-maint/Lib/cgitb.py (original) +++ python/branches/release25-maint/Lib/cgitb.py Sat Apr 21 09:28:26 2007 @@ -167,7 +167,7 @@ exception = ['

%s: %s' % (strong(pydoc.html.escape(str(etype))), pydoc.html.escape(str(evalue)))] - if type(evalue) is types.InstanceType: + if isinstance(evalue, BaseException): for name in dir(evalue): if name[:1] == '_': continue value = pydoc.html.repr(getattr(evalue, name)) @@ -239,7 +239,7 @@ frames.append('\n%s\n' % '\n'.join(rows)) exception = ['%s: %s' % (str(etype), str(evalue))] - if type(evalue) is types.InstanceType: + if isinstance(evalue, BaseException): for name in dir(evalue): value = pydoc.text.repr(getattr(evalue, name)) exception.append('\n%s%s = %s' % (" "*4, name, value)) From python-checkins at python.org Sat Apr 21 09:30:55 2007 From: python-checkins at python.org (georg.brandl) Date: Sat, 21 Apr 2007 09:30:55 +0200 (CEST) Subject: [Python-checkins] r54906 - python/branches/release25-maint/Doc/texinputs/python.sty Message-ID: <20070421073055.05A551E4003@bag.python.org> Author: georg.brandl Date: Sat Apr 21 09:30:52 2007 New Revision: 54906 Modified: python/branches/release25-maint/Doc/texinputs/python.sty Log: Backport r54671 - fix in python.sty. Modified: python/branches/release25-maint/Doc/texinputs/python.sty ============================================================================== --- python/branches/release25-maint/Doc/texinputs/python.sty (original) +++ python/branches/release25-maint/Doc/texinputs/python.sty Sat Apr 21 09:30:52 2007 @@ -612,7 +612,7 @@ \newenvironment{cfuncdesc}[4][\py at badkey]{ \begin{fulllineitems} \cfuncline{#2}{#3}{#4} - \ifx#1\@undefined\else% + \ifx\@undefined#1\relax\else% \emph{Return value: \textbf{#1}.}\\ \fi }{\end{fulllineitems}} @@ -629,7 +629,7 @@ \newenvironment{ctypedesc}[2][\py at badkey]{ \begin{fulllineitems} \item[\bfcode{#2}% - \ifx#1\@undefined% + \ifx\@undefined#1\relax% \index{#2@{\py at idxcode{#2}} (C type)} \else% \index{#2@{\py at idxcode{#1}} (C type)} @@ -712,7 +712,7 @@ % \begin{methoddesc}[classname]{methodname}{args} \newcommand{\methodline}[3][\@undefined]{ \methodlineni{#2}{#3} - \ifx#1\@undefined + \ifx\@undefined#1\relax \index{#2@{\py at idxcode{#2()}} (\py at thisclass\ method)} \else \index{#2@{\py at idxcode{#2()}} (#1 method)} @@ -720,7 +720,7 @@ } \newenvironment{methoddesc}[3][\@undefined]{ \begin{fulllineitems} - \ifx#1\@undefined + \ifx\@undefined#1\relax \methodline{#2}{#3} \else \def\py at thisclass{#1} @@ -740,7 +740,7 @@ % object data attribute -------------------------------------------------- % \begin{memberdesc}[classname]{membername} \newcommand{\memberline}[2][\py at classbadkey]{% - \ifx#1\@undefined + \ifx\@undefined#1\relax \memberlineni{#2} \index{#2@{\py at idxcode{#2}} (\py at thisclass\ attribute)} \else @@ -750,7 +750,7 @@ } \newenvironment{memberdesc}[2][\py at classbadkey]{ \begin{fulllineitems} - \ifx#1\@undefined + \ifx\@undefined#1\relax \memberline{#2} \else \def\py at thisclass{#1} @@ -1046,14 +1046,14 @@ % \versionchanged[short explanation]{2.0} % \newcommand{\versionadded}[2][\py at badkey]{% - \ifx#1\@undefined% + \ifx\@undefined#1\relax% { New in version #2. }% \else% { New in version #2:\ #1. }% \fi% } \newcommand{\versionchanged}[2][\py at badkey]{% - \ifx#1\@undefined% + \ifx\@undefined#1\relax% { Changed in version #2. }% \else% { Changed in version #2:\ #1. }% From nnorwitz at gmail.com Sat Apr 21 11:18:55 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sat, 21 Apr 2007 05:18:55 -0400 Subject: [Python-checkins] Python Regression Test Failures refleak (1) Message-ID: <20070421091855.GA28050@python.psfb.org> test_cmd_line leaked [-17, 0, 0] references test_threadsignals leaked [0, 0, -8] references From python-checkins at python.org Sat Apr 21 12:31:45 2007 From: python-checkins at python.org (walter.doerwald) Date: Sat, 21 Apr 2007 12:31:45 +0200 (CEST) Subject: [Python-checkins] r54907 - in python/branches/release25-maint: Lib/encodings/utf_8_sig.py Lib/test/test_codecs.py Misc/NEWS Message-ID: <20070421103145.E41171E4003@bag.python.org> Author: walter.doerwald Date: Sat Apr 21 12:31:43 2007 New Revision: 54907 Modified: python/branches/release25-maint/Lib/encodings/utf_8_sig.py python/branches/release25-maint/Lib/test/test_codecs.py python/branches/release25-maint/Misc/NEWS Log: Backport r54786: Fix utf-8-sig incremental decoder, which didn't recognise a BOM when the first chunk fed to the decoder started with a BOM, but was longer than 3 bytes. Modified: python/branches/release25-maint/Lib/encodings/utf_8_sig.py ============================================================================== --- python/branches/release25-maint/Lib/encodings/utf_8_sig.py (original) +++ python/branches/release25-maint/Lib/encodings/utf_8_sig.py Sat Apr 21 12:31:43 2007 @@ -44,14 +44,19 @@ self.first = True def _buffer_decode(self, input, errors, final): - if self.first and codecs.BOM_UTF8.startswith(input): # might be a BOM + if self.first: if len(input) < 3: - # not enough data to decide if this really is a BOM - # => try again on the next call - return (u"", 0) - (output, consumed) = codecs.utf_8_decode(input[3:], errors, final) - self.first = False - return (output, consumed+3) + if codecs.BOM_UTF8.startswith(input): + # not enough data to decide if this really is a BOM + # => try again on the next call + return (u"", 0) + else: + self.first = None + else: + self.first = None + if input[:3] == codecs.BOM_UTF8: + (output, consumed) = codecs.utf_8_decode(input[3:], errors, final) + return (output, consumed+3) return codecs.utf_8_decode(input, errors, final) def reset(self): Modified: python/branches/release25-maint/Lib/test/test_codecs.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_codecs.py (original) +++ python/branches/release25-maint/Lib/test/test_codecs.py Sat Apr 21 12:31:43 2007 @@ -430,6 +430,11 @@ # SF bug #1601501: check that the codec works with a buffer unicode("\xef\xbb\xbf", "utf-8-sig") + def test_bom(self): + d = codecs.getincrementaldecoder("utf-8-sig")() + s = u"spam" + self.assertEqual(d.decode(s.encode("utf-8-sig")), s) + class EscapeDecodeTest(unittest.TestCase): def test_empty(self): self.assertEquals(codecs.escape_decode(""), ("", 0)) Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Sat Apr 21 12:31:43 2007 @@ -602,6 +602,8 @@ - Fix bsddb test_basics.test06_Transactions to check the version number properly. +- Fix utf-8-sig incremental decoder, which didn't recognise a BOM when the + first chunk fed to the decoder started with a BOM, but was longer than 3 bytes. Documentation ------------- From buildbot at python.org Sat Apr 21 14:19:30 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 12:19:30 +0000 Subject: [Python-checkins] buildbot warnings in hppa Ubuntu dapper 2.5 Message-ID: <20070421121931.27DD11E4003@bag.python.org> The Buildbot has detected a new failure of hppa Ubuntu dapper 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/hppa%2520Ubuntu%2520dapper%25202.5/builds/82 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: walter.doerwald Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sat Apr 21 14:20:13 2007 From: python-checkins at python.org (lars.gustaebel) Date: Sat, 21 Apr 2007 14:20:13 +0200 (CEST) Subject: [Python-checkins] r54908 - python/branches/release25-maint/Lib/tarfile.py Message-ID: <20070421122013.6FB241E400F@bag.python.org> Author: lars.gustaebel Date: Sat Apr 21 14:20:09 2007 New Revision: 54908 Modified: python/branches/release25-maint/Lib/tarfile.py Log: Support for unicode strings as input filenames is neither documented nor intended but works in Python 2.4 under certain conditions. This stopped working in 2.5 because struct.pack is used. This small patch restores the old behaviour. A more solid solution is planned for 2.6. Modified: python/branches/release25-maint/Lib/tarfile.py ============================================================================== --- python/branches/release25-maint/Lib/tarfile.py (original) +++ python/branches/release25-maint/Lib/tarfile.py Sat Apr 21 14:20:09 2007 @@ -963,7 +963,7 @@ stn(prefix, 155) ] - buf += struct.pack("%ds" % BLOCKSIZE, "".join(parts)) + buf += "".join(parts).ljust(BLOCKSIZE, NUL) chksum = calc_chksums(buf[-BLOCKSIZE:])[0] buf = buf[:-364] + "%06o\0" % chksum + buf[-357:] self.buf = buf From python-checkins at python.org Sat Apr 21 14:30:39 2007 From: python-checkins at python.org (lars.gustaebel) Date: Sat, 21 Apr 2007 14:30:39 +0200 (CEST) Subject: [Python-checkins] r54908 - svn:log Message-ID: <20070421123039.446B21E4003@bag.python.org> Author: lars.gustaebel Revision: 54908 Property Name: svn:log New Property Value: Bug #1704156: Support for unicode strings as input filenames is neither documented nor intended but works in Python 2.4 under certain conditions. This stopped working in 2.5 because struct.pack is used. This small patch restores the old behaviour. A more solid solution is planned for 2.6. From python-checkins at python.org Sat Apr 21 14:46:56 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Sat, 21 Apr 2007 14:46:56 +0200 (CEST) Subject: [Python-checkins] r54909 - in python/branches/release25-maint: Modules/_ctypes/callproc.c Modules/binascii.c Modules/cPickle.c Modules/cStringIO.c Modules/posixmodule.c PC/_winreg.c Python/dynload_win.c Python/thread_nt.h Message-ID: <20070421124656.ED0081E4003@bag.python.org> Author: kristjan.jonsson Date: Sat Apr 21 14:46:49 2007 New Revision: 54909 Modified: python/branches/release25-maint/Modules/_ctypes/callproc.c python/branches/release25-maint/Modules/binascii.c python/branches/release25-maint/Modules/cPickle.c python/branches/release25-maint/Modules/cStringIO.c python/branches/release25-maint/Modules/posixmodule.c python/branches/release25-maint/PC/_winreg.c python/branches/release25-maint/Python/dynload_win.c python/branches/release25-maint/Python/thread_nt.h Log: Fix various minor issues discovered with static analysis using Visual Studio 2005 Team System. Removed obsolete comment, since .dll modules are no longer supported on windows, only .pyd. Modified: python/branches/release25-maint/Modules/_ctypes/callproc.c ============================================================================== --- python/branches/release25-maint/Modules/_ctypes/callproc.c (original) +++ python/branches/release25-maint/Modules/_ctypes/callproc.c Sat Apr 21 14:46:49 2007 @@ -64,6 +64,7 @@ #ifdef MS_WIN32 #include +#include #else #include "ctypes_dlfcn.h" #endif @@ -97,9 +98,9 @@ 0, NULL); if (n) { - while (isspace(lpMsgBuf[n-1])) + while (_istspace(lpMsgBuf[n-1])) --n; - lpMsgBuf[n] = '\0'; /* rstrip() */ + lpMsgBuf[n] = _T('\0'); /* rstrip() */ } return lpMsgBuf; } Modified: python/branches/release25-maint/Modules/binascii.c ============================================================================== --- python/branches/release25-maint/Modules/binascii.c (original) +++ python/branches/release25-maint/Modules/binascii.c Sat Apr 21 14:46:49 2007 @@ -1165,7 +1165,8 @@ ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || ((data[in] < 33) && (data[in] != '\r') && (data[in] != '\n') && - (quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) + (!quotetabs || + (quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) { if ((linelen + 3) >= MAXLINESIZE) { linelen = 0; @@ -1235,7 +1236,8 @@ ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || ((data[in] < 33) && (data[in] != '\r') && (data[in] != '\n') && - (quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) + (!quotetabs || + (quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) { if ((linelen + 3 )>= MAXLINESIZE) { odata[out++] = '='; Modified: python/branches/release25-maint/Modules/cPickle.c ============================================================================== --- python/branches/release25-maint/Modules/cPickle.c (original) +++ python/branches/release25-maint/Modules/cPickle.c Sat Apr 21 14:46:49 2007 @@ -533,11 +533,12 @@ self->buf_size = size; } else if (n > self->buf_size) { - self->buf = (char *)realloc(self->buf, n); - if (!self->buf) { + char *newbuf = (char *)realloc(self->buf, n); + if (!newbuf) { PyErr_NoMemory(); return -1; } + self->buf = newbuf; self->buf_size = n; } @@ -576,6 +577,7 @@ i = 0; while (1) { int bigger; + char *newbuf; for (; i < (self->buf_size - 1); i++) { if (feof(self->fp) || (self->buf[i] = getc(self->fp)) == '\n') { @@ -589,11 +591,12 @@ PyErr_NoMemory(); return -1; } - self->buf = (char *)realloc(self->buf, bigger); - if (!self->buf) { + newbuf = (char *)realloc(self->buf, bigger); + if (!newbuf) { PyErr_NoMemory(); return -1; } + self->buf = newbuf; self->buf_size = bigger; } } @@ -4365,17 +4368,19 @@ */ if ((self->num_marks + 1) >= self->marks_size) { + int *marks; s=self->marks_size+20; if (s <= self->num_marks) s=self->num_marks + 1; if (self->marks == NULL) - self->marks=(int *)malloc(s * sizeof(int)); + marks=(int *)malloc(s * sizeof(int)); else - self->marks=(int *)realloc(self->marks, + marks=(int *)realloc(self->marks, s * sizeof(int)); - if (! self->marks) { + if (!marks) { PyErr_NoMemory(); return -1; } + self->marks = marks; self->marks_size = s; } Modified: python/branches/release25-maint/Modules/cStringIO.c ============================================================================== --- python/branches/release25-maint/Modules/cStringIO.c (original) +++ python/branches/release25-maint/Modules/cStringIO.c Sat Apr 21 14:46:49 2007 @@ -339,13 +339,17 @@ } if (position > self->buf_size) { + char *newbuf; self->buf_size*=2; if (self->buf_size <= position) self->buf_size=position+1; - self->buf = (char*) realloc(self->buf,self->buf_size); - if (!self->buf) { + newbuf = (char*) realloc(self->buf,self->buf_size); + if (!newbuf) { + free(self->buf); + self->buf = 0; self->buf_size=self->pos=0; return PyErr_NoMemory(); } + self->buf = newbuf; } else if (position < 0) position=0; @@ -366,6 +370,7 @@ O_cwrite(PyObject *self, const char *c, Py_ssize_t l) { Py_ssize_t newl; Oobject *oself; + char *newbuf; if (!IO__opencheck(IOOOBJECT(self))) return -1; oself = (Oobject *)self; @@ -377,12 +382,15 @@ assert(newl + 1 < INT_MAX); oself->buf_size = (int)(newl+1); } - oself->buf = (char*)realloc(oself->buf, oself->buf_size); - if (!oself->buf) { + newbuf = (char*)realloc(oself->buf, oself->buf_size); + if (!newbuf) { PyErr_SetString(PyExc_MemoryError,"out of memory"); + free(oself->buf); + oself->buf = 0; oself->buf_size = oself->pos = 0; return -1; } + oself->buf = newbuf; } memcpy(oself->buf+oself->pos,c,l); Modified: python/branches/release25-maint/Modules/posixmodule.c ============================================================================== --- python/branches/release25-maint/Modules/posixmodule.c (original) +++ python/branches/release25-maint/Modules/posixmodule.c Sat Apr 21 14:46:49 2007 @@ -4788,18 +4788,19 @@ (sizeof(modulepath)/sizeof(modulepath[0])) -strlen(modulepath)); if (stat(modulepath, &statinfo) != 0) { + size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]); /* Eeek - file-not-found - possibly an embedding situation - see if we can locate it in sys.prefix */ strncpy(modulepath, Py_GetExecPrefix(), - sizeof(modulepath)/sizeof(modulepath[0])); + mplen); + modulepath[mplen-1] = '\0'; if (modulepath[strlen(modulepath)-1] != '\\') strcat(modulepath, "\\"); strncat(modulepath, szConsoleSpawn, - (sizeof(modulepath)/sizeof(modulepath[0])) - -strlen(modulepath)); + mplen-strlen(modulepath)); /* No where else to look - raise an easily identifiable error, rather than leaving Windows to report "file not found" - as the user is probably blissfully Modified: python/branches/release25-maint/PC/_winreg.c ============================================================================== --- python/branches/release25-maint/PC/_winreg.c (original) +++ python/branches/release25-maint/PC/_winreg.c Sat Apr 21 14:46:49 2007 @@ -699,7 +699,7 @@ case REG_DWORD: if (value != Py_None && !PyInt_Check(value)) return FALSE; - *retDataBuf = (BYTE *)PyMem_NEW(DWORD, sizeof(DWORD)); + *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1); if (*retDataBuf==NULL){ PyErr_NoMemory(); return FALSE; Modified: python/branches/release25-maint/Python/dynload_win.c ============================================================================== --- python/branches/release25-maint/Python/dynload_win.c (original) +++ python/branches/release25-maint/Python/dynload_win.c Sat Apr 21 14:46:49 2007 @@ -13,16 +13,8 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef _DEBUG {"_d.pyd", "rb", C_EXTENSION}, - /* Temporarily disable .dll, to avoid conflicts between sqlite3.dll - and the sqlite3 package. If this needs to be reverted for 2.5, - some other solution for the naming conflict must be found. - {"_d.dll", "rb", C_EXTENSION}, - */ #else {".pyd", "rb", C_EXTENSION}, - /* Likewise - {".dll", "rb", C_EXTENSION}, - */ #endif {0, 0} }; Modified: python/branches/release25-maint/Python/thread_nt.h ============================================================================== --- python/branches/release25-maint/Python/thread_nt.h (original) +++ python/branches/release25-maint/Python/thread_nt.h Sat Apr 21 14:46:49 2007 @@ -202,12 +202,12 @@ * too many threads". */ dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n", - PyThread_get_thread_ident(), rv, errno)); + PyThread_get_thread_ident(), (void*)rv, errno)); obj.id = -1; } else { dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", - PyThread_get_thread_ident(), rv)); + PyThread_get_thread_ident(), (void*)rv)); /* wait for thread to initialize, so we can get its id */ WaitForSingleObject(obj.done, INFINITE); assert(obj.id != -1); @@ -333,7 +333,7 @@ dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); + dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError())); } /* minimum/maximum thread stack sizes supported */ From buildbot at python.org Sat Apr 21 15:10:17 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 13:10:17 +0000 Subject: [Python-checkins] buildbot warnings in x86 gentoo 2.5 Message-ID: <20070421131017.489E31E4003@bag.python.org> The Buildbot has detected a new failure of x86 gentoo 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520gentoo%25202.5/builds/329 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/python-trunk/2.5.norwitz-x86/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/buildslave/python-trunk/2.5.norwitz-x86/build/Lib/test/test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/python-trunk/2.5.norwitz-x86/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/buildslave/python-trunk/2.5.norwitz-x86/build/Lib/test/test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/python-trunk/2.5.norwitz-x86/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/buildslave/python-trunk/2.5.norwitz-x86/build/Lib/test/test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/python-trunk/2.5.norwitz-x86/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/buildslave/python-trunk/2.5.norwitz-x86/build/Lib/test/test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/python-trunk/2.5.norwitz-x86/build/Lib/test/test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Apr 21 15:10:31 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 13:10:31 +0000 Subject: [Python-checkins] buildbot warnings in amd64 gentoo 2.5 Message-ID: <20070421131031.BDBA41E4003@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%2520gentoo%25202.5/builds/287 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/2.5.norwitz-amd64/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/buildbot/slave/py-build/2.5.norwitz-amd64/build/Lib/test/test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/2.5.norwitz-amd64/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/buildbot/slave/py-build/2.5.norwitz-amd64/build/Lib/test/test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/2.5.norwitz-amd64/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/buildbot/slave/py-build/2.5.norwitz-amd64/build/Lib/test/test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/2.5.norwitz-amd64/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/buildbot/slave/py-build/2.5.norwitz-amd64/build/Lib/test/test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/2.5.norwitz-amd64/build/Lib/test/test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Apr 21 15:14:54 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 13:14:54 +0000 Subject: [Python-checkins] buildbot warnings in x86 mvlgcc 2.5 Message-ID: <20070421131454.B22661E4003@bag.python.org> The Buildbot has detected a new failure of x86 mvlgcc 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520mvlgcc%25202.5/builds/206 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/2.5.loewis-linux/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home2/buildbot/slave/2.5.loewis-linux/build/Lib/test/test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/2.5.loewis-linux/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home2/buildbot/slave/2.5.loewis-linux/build/Lib/test/test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/2.5.loewis-linux/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home2/buildbot/slave/2.5.loewis-linux/build/Lib/test/test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/2.5.loewis-linux/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home2/buildbot/slave/2.5.loewis-linux/build/Lib/test/test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/2.5.loewis-linux/build/Lib/test/test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Apr 21 15:16:02 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 13:16:02 +0000 Subject: [Python-checkins] buildbot warnings in x86 W2k 2.5 Message-ID: <20070421131602.000F91E4003@bag.python.org> The Buildbot has detected a new failure of x86 W2k 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520W2k%25202.5/builds/86 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\2.5.mick-windows\build\lib\test\test_quopri.py", line 50, in newtest testfunc(self) File "C:\trentm\data\buildbot\python-slave\2.5.mick-windows\build\lib\test\test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\2.5.mick-windows\build\lib\test\test_quopri.py", line 50, in newtest testfunc(self) File "C:\trentm\data\buildbot\python-slave\2.5.mick-windows\build\lib\test\test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\2.5.mick-windows\build\lib\test\test_quopri.py", line 50, in newtest testfunc(self) File "C:\trentm\data\buildbot\python-slave\2.5.mick-windows\build\lib\test\test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\2.5.mick-windows\build\lib\test\test_quopri.py", line 50, in newtest testfunc(self) File "C:\trentm\data\buildbot\python-slave\2.5.mick-windows\build\lib\test\test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\trentm\data\buildbot\python-slave\2.5.mick-windows\build\lib\test\test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError sincerely, -The Buildbot From buildbot at python.org Sat Apr 21 15:37:28 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 13:37:28 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP 2.5 Message-ID: <20070421133728.BF76A1E400B@bag.python.org> The Buildbot has detected a new failure of x86 XP 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%25202.5/builds/207 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\2.5.mcintyre-windows\build\lib\test\test_quopri.py", line 50, in newtest testfunc(self) File "C:\buildbot_py25\2.5.mcintyre-windows\build\lib\test\test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\2.5.mcintyre-windows\build\lib\test\test_quopri.py", line 50, in newtest testfunc(self) File "C:\buildbot_py25\2.5.mcintyre-windows\build\lib\test\test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\2.5.mcintyre-windows\build\lib\test\test_quopri.py", line 50, in newtest testfunc(self) File "C:\buildbot_py25\2.5.mcintyre-windows\build\lib\test\test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\2.5.mcintyre-windows\build\lib\test\test_quopri.py", line 50, in newtest testfunc(self) File "C:\buildbot_py25\2.5.mcintyre-windows\build\lib\test\test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\buildbot_py25\2.5.mcintyre-windows\build\lib\test\test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError sincerely, -The Buildbot From buildbot at python.org Sat Apr 21 15:40:24 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 13:40:24 +0000 Subject: [Python-checkins] buildbot warnings in sparc solaris10 gcc 2.5 Message-ID: <20070421134024.1A2B51E4003@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%2520solaris10%2520gcc%25202.5/builds/313 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/opt/users/buildbot/slave/2.5.loewis-sun/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/opt/users/buildbot/slave/2.5.loewis-sun/build/Lib/test/test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/opt/users/buildbot/slave/2.5.loewis-sun/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/opt/users/buildbot/slave/2.5.loewis-sun/build/Lib/test/test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/opt/users/buildbot/slave/2.5.loewis-sun/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/opt/users/buildbot/slave/2.5.loewis-sun/build/Lib/test/test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/opt/users/buildbot/slave/2.5.loewis-sun/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/opt/users/buildbot/slave/2.5.loewis-sun/build/Lib/test/test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/opt/users/buildbot/slave/2.5.loewis-sun/build/Lib/test/test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError sincerely, -The Buildbot From buildbot at python.org Sat Apr 21 15:42:22 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 13:42:22 +0000 Subject: [Python-checkins] buildbot warnings in g4 osx.4 2.5 Message-ID: <20070421134223.120CA1E4003@bag.python.org> The Buildbot has detected a new failure of g4 osx.4 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/g4%2520osx.4%25202.5/builds/315 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildslave/bb/2.5.psf-g4/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/Users/buildslave/bb/2.5.psf-g4/build/Lib/test/test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildslave/bb/2.5.psf-g4/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/Users/buildslave/bb/2.5.psf-g4/build/Lib/test/test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildslave/bb/2.5.psf-g4/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/Users/buildslave/bb/2.5.psf-g4/build/Lib/test/test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildslave/bb/2.5.psf-g4/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/Users/buildslave/bb/2.5.psf-g4/build/Lib/test/test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildslave/bb/2.5.psf-g4/build/Lib/test/test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Apr 21 15:59:37 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 13:59:37 +0000 Subject: [Python-checkins] buildbot warnings in ia64 Ubuntu trunk 2.5 Message-ID: <20070421135937.A272F1E4003@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%2520Ubuntu%2520trunk%25202.5/builds/276 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-ia64/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-ia64/build/Lib/test/test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-ia64/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-ia64/build/Lib/test/test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-ia64/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-ia64/build/Lib/test/test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-ia64/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-ia64/build/Lib/test/test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-ia64/build/Lib/test/test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Apr 21 16:11:52 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 14:11:52 +0000 Subject: [Python-checkins] buildbot warnings in S-390 Debian 2.5 Message-ID: <20070421141152.686FA1E4003@bag.python.org> The Buildbot has detected a new failure of S-390 Debian 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/S-390%2520Debian%25202.5/builds/263 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-s390/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-s390/build/Lib/test/test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-s390/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-s390/build/Lib/test/test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-s390/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-s390/build/Lib/test/test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-s390/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-s390/build/Lib/test/test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-s390/build/Lib/test/test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Apr 21 16:34:03 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 14:34:03 +0000 Subject: [Python-checkins] buildbot warnings in hppa Ubuntu dapper 2.5 Message-ID: <20070421143403.2D3D81E4003@bag.python.org> The Buildbot has detected a new failure of hppa Ubuntu dapper 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/hppa%2520Ubuntu%2520dapper%25202.5/builds/84 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sat Apr 21 17:50:51 2007 From: python-checkins at python.org (georg.brandl) Date: Sat, 21 Apr 2007 17:50:51 +0200 (CEST) Subject: [Python-checkins] r54911 - peps/trunk/pep-3114.txt Message-ID: <20070421155051.A6BD01E4010@bag.python.org> Author: georg.brandl Date: Sat Apr 21 17:50:50 2007 New Revision: 54911 Modified: peps/trunk/pep-3114.txt Log: PEP 3114 is final. Modified: peps/trunk/pep-3114.txt ============================================================================== --- peps/trunk/pep-3114.txt (original) +++ peps/trunk/pep-3114.txt Sat Apr 21 17:50:50 2007 @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Ka-Ping Yee -Status: Accepted +Status: Final Type: Standards Track Python-version: 3.0 Content-Type: text/x-rst @@ -179,6 +179,13 @@ This PEP was accepted by Guido on March 6, 2007 [5]_. +Implementation +============== + +A patch with the necessary changes (except the 2to3 tool) was written +by Georg Brandl and committed as revision 54910. + + References ========== From python-checkins at python.org Sat Apr 21 17:51:53 2007 From: python-checkins at python.org (georg.brandl) Date: Sat, 21 Apr 2007 17:51:53 +0200 (CEST) Subject: [Python-checkins] r54912 - peps/trunk/pep-0000.txt Message-ID: <20070421155153.3A75A1E4005@bag.python.org> Author: georg.brandl Date: Sat Apr 21 17:51:51 2007 New Revision: 54912 Modified: peps/trunk/pep-0000.txt Log: Update PEP 0. Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Sat Apr 21 17:51:51 2007 @@ -113,7 +113,6 @@ S 754 IEEE 754 Floating Point Special Values Warnes S 3101 Advanced String Formatting Talin S 3108 Standard Library Reorganization Cannon - S 3114 Renaming iterator.next() to iterator.__next__() Yee S 3116 New I/O Stutzbach, Verdone, GvR S 3117 Postfix Type Declarations Brandl S 3118 Revising the buffer protocol Oliphant, Banks @@ -182,6 +181,7 @@ SF 3104 Access to Names in Outer Scopes Yee SF 3105 Make print a function Brandl SF 3107 Function Annotations Winter, Lownds + SF 3114 Renaming iterator.next() to iterator.__next__() Yee Empty PEPs (or containing only an abstract) @@ -467,7 +467,7 @@ SA 3111 Simple input built-in in Python 3000 Roberge SA 3112 Bytes literals in Python 3000 Orendorff SA 3113 Removal of Tuple Parameter Unpacking Cannon - S 3114 Renaming iterator.next() to iterator.__next__() Yee + SF 3114 Renaming iterator.next() to iterator.__next__() Yee SA 3115 Metaclasses in Python 3000 Talin S 3116 New I/O Stutzbach, Verdone, GvR S 3117 Postfix Type Declarations Brandl From buildbot at python.org Sat Apr 21 18:03:01 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 16:03:01 +0000 Subject: [Python-checkins] buildbot warnings in alpha Debian 2.5 Message-ID: <20070421160301.92C661E4003@bag.python.org> The Buildbot has detected a new failure of alpha Debian 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Debian%25202.5/builds/8 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-alpha/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-alpha/build/Lib/test/test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-alpha/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-alpha/build/Lib/test/test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-alpha/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-alpha/build/Lib/test/test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-alpha/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-alpha/build/Lib/test/test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-alpha/build/Lib/test/test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sat Apr 21 18:42:56 2007 From: python-checkins at python.org (erik.forsberg) Date: Sat, 21 Apr 2007 18:42:56 +0200 (CEST) Subject: [Python-checkins] r54913 - tracker/roundup-src/roundup/cgi/client.py Message-ID: <20070421164256.3C2791E4003@bag.python.org> Author: erik.forsberg Date: Sat Apr 21 18:42:55 2007 New Revision: 54913 Modified: tracker/roundup-src/roundup/cgi/client.py Log: Try to cope with http://sourceforge.net/tracker/index.php?func=detail&aid=1703116&group_id=31577&atid=402788 which is causing large amounts of mail from the tracker. Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Sat Apr 21 18:42:55 2007 @@ -349,9 +349,28 @@ if now - last_clean < hour: return + # This is a bit ugly, but right now, I'm too lazy to fix a new API + # in all rdbms-based backends to cope with this problem that only + # appears on Postgres. + try: + from psycopg import ProgrammingError + except ImportError: + from psycopg2.psycopg1 import ProgrammingError + except ImportError: + ProgrammingError = None + sessions.clean(now) self.db.getOTKManager().clean(now) - sessions.set('last_clean', last_use=time.time()) + try: + sessions.set('last_clean', last_use=time.time()) + except ProgrammingError, err: + response = str(err).split('\n')[0] + if -1 != response.find('ERROR') and \ + -1 != response.find('could not serialize access due to concurrent update'): + # Another client just updated, and we're running on + # serializable isolation. + # See http://www.postgresql.org/docs/7.4/interactive/transaction-iso.html + return self.db.commit(fail_ok=True) def determine_charset(self): From python-checkins at python.org Sat Apr 21 18:56:05 2007 From: python-checkins at python.org (erik.forsberg) Date: Sat, 21 Apr 2007 18:56:05 +0200 (CEST) Subject: [Python-checkins] r54914 - tracker/roundup-src/roundup/cgi/templating.py Message-ID: <20070421165605.19F5E1E4003@bag.python.org> Author: erik.forsberg Date: Sat Apr 21 18:56:04 2007 New Revision: 54914 Modified: tracker/roundup-src/roundup/cgi/templating.py Log: Work around http://psf.upfronthosting.co.za/roundup/meta/issue111 - roundup not being fault-tolerant enough about multiple form values. Modified: tracker/roundup-src/roundup/cgi/templating.py ============================================================================== --- tracker/roundup-src/roundup/cgi/templating.py (original) +++ tracker/roundup-src/roundup/cgi/templating.py Sat Apr 21 18:56:04 2007 @@ -2231,7 +2231,13 @@ for name in ':search_text @search_text'.split(): if self.form.has_key(name): self.special_char = name[0] - self.search_text = self.form[name].value + try: + self.search_text = self.form[name].value + except AttributeError: + # http://psf.upfronthosting.co.za/roundup/meta/issue111 + # Multiple search_text, probably some kind of spambot. + # Use first value. + self.search_text = self.form[name][0].value # pagination - size and start index # figure batch args From buildbot at python.org Sat Apr 21 19:23:55 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Apr 2007 17:23:55 +0000 Subject: [Python-checkins] buildbot warnings in MIPS Debian 2.5 Message-ID: <20070421172355.A4BD71E4003@bag.python.org> The Buildbot has detected a new failure of MIPS Debian 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/MIPS%2520Debian%25202.5/builds/208 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: kristjan.jonsson,lars.gustaebel Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_quopri ====================================================================== FAIL: test_embedded_ws (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-mips/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-mips/build/Lib/test/test_quopri.py", line 164, in test_embedded_ws self.assert_(quopri.encodestring(p, quotetabs=True) == e) AssertionError ====================================================================== FAIL: test_encode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-mips/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-mips/build/Lib/test/test_quopri.py", line 151, in test_encode self.assert_(outfp.getvalue() == e) AssertionError ====================================================================== FAIL: test_encode_header (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-mips/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-mips/build/Lib/test/test_quopri.py", line 170, in test_encode_header self.assert_(quopri.encodestring(p, header=True) == e) AssertionError ====================================================================== FAIL: test_encodestring (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-mips/build/Lib/test/test_quopri.py", line 50, in newtest testfunc(self) File "/home/pybot/buildarea/2.5.klose-debian-mips/build/Lib/test/test_quopri.py", line 133, in test_encodestring self.assert_(quopri.encodestring(p) == e) AssertionError ====================================================================== FAIL: test_scriptencode (test.test_quopri.QuopriTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.5.klose-debian-mips/build/Lib/test/test_quopri.py", line 185, in test_scriptencode self.assert_(cout.splitlines() == e.splitlines()) AssertionError make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sat Apr 21 19:43:46 2007 From: python-checkins at python.org (erik.forsberg) Date: Sat, 21 Apr 2007 19:43:46 +0200 (CEST) Subject: [Python-checkins] r54915 - tracker/importer/sfxmlhandlers.py Message-ID: <20070421174346.D02841E4003@bag.python.org> Author: erik.forsberg Date: Sat Apr 21 19:43:45 2007 New Revision: 54915 Modified: tracker/importer/sfxmlhandlers.py Log: Merge 2.2.x -> 2.2 and 2.1.x -> 2.1 as specified in http://psf.upfronthosting.co.za/roundup/meta/issue101. Modified: tracker/importer/sfxmlhandlers.py ============================================================================== --- tracker/importer/sfxmlhandlers.py (original) +++ tracker/importer/sfxmlhandlers.py Sat Apr 21 19:43:45 2007 @@ -423,6 +423,11 @@ elif "Python 3000" == group: roundupdata['keywords'].append(self.db.keyword.lookup('py3k')) try: + # Merge as specified in http://psf.upfronthosting.co.za/roundup/meta/issue101 + if group.startswith("Python 2.1"): + group = "Python 2.1" + elif group.startswith("Python 2.2"): + group = "Python 2.2" version = self.db.version.lookup(group) roundupdata[self.target] = version return From python-checkins at python.org Sat Apr 21 21:49:03 2007 From: python-checkins at python.org (erik.forsberg) Date: Sat, 21 Apr 2007 21:49:03 +0200 (CEST) Subject: [Python-checkins] r54916 - tracker/instances/python-dev/detectors/config.ini Message-ID: <20070421194903.C0BF31E4003@bag.python.org> Author: erik.forsberg Date: Sat Apr 21 21:49:00 2007 New Revision: 54916 Modified: tracker/instances/python-dev/detectors/config.ini Log: Use correct mail addresses. Modified: tracker/instances/python-dev/detectors/config.ini ============================================================================== --- tracker/instances/python-dev/detectors/config.ini (original) +++ tracker/instances/python-dev/detectors/config.ini Sat Apr 21 21:49:00 2007 @@ -2,7 +2,7 @@ # The two definitions can be comma-delimited lists of email addresses. # Be sure these addresses will accept mail from the tracker's email address. [main] -triage_email= new-bugs-announce at python.org,python-bug-list at python.org -busybody_email= python-bug-list at python.org +triage_email= new-bugs-announce at python.org,python-bugs-list at python.org +busybody_email= python-bugs-list at python.org From g.brandl at gmx.net Sat Apr 21 22:27:13 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Sat, 21 Apr 2007 22:27:13 +0200 Subject: [Python-checkins] r54913 - tracker/roundup-src/roundup/cgi/client.py In-Reply-To: <20070421164256.3C2791E4003@bag.python.org> References: <20070421164256.3C2791E4003@bag.python.org> Message-ID: erik.forsberg schrieb: > Modified: tracker/roundup-src/roundup/cgi/client.py > ============================================================================== > --- tracker/roundup-src/roundup/cgi/client.py (original) > +++ tracker/roundup-src/roundup/cgi/client.py Sat Apr 21 18:42:55 2007 > @@ -349,9 +349,28 @@ > if now - last_clean < hour: > return > > + # This is a bit ugly, but right now, I'm too lazy to fix a new API > + # in all rdbms-based backends to cope with this problem that only > + # appears on Postgres. > + try: > + from psycopg import ProgrammingError > + except ImportError: > + from psycopg2.psycopg1 import ProgrammingError > + except ImportError: > + ProgrammingError = None Note that this doesn't work as intended... you'll have to nest a try block. Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out. From python-checkins at python.org Sat Apr 21 22:35:43 2007 From: python-checkins at python.org (georg.brandl) Date: Sat, 21 Apr 2007 22:35:43 +0200 (CEST) Subject: [Python-checkins] r54918 - python/trunk/Lib/subprocess.py Message-ID: <20070421203543.2A4E71E4017@bag.python.org> Author: georg.brandl Date: Sat Apr 21 22:35:38 2007 New Revision: 54918 Modified: python/trunk/Lib/subprocess.py Log: Bug #1704790: bind name "sys" locally in __del__ method so that it is not cleared before __del__ is run. Modified: python/trunk/Lib/subprocess.py ============================================================================== --- python/trunk/Lib/subprocess.py (original) +++ python/trunk/Lib/subprocess.py Sat Apr 21 22:35:38 2007 @@ -628,7 +628,7 @@ return data - def __del__(self): + def __del__(self, sys=sys): if not self._child_created: # We didn't get to successfully create a child process. return From python-checkins at python.org Sat Apr 21 22:35:51 2007 From: python-checkins at python.org (georg.brandl) Date: Sat, 21 Apr 2007 22:35:51 +0200 (CEST) Subject: [Python-checkins] r54919 - python/branches/release25-maint/Lib/subprocess.py Message-ID: <20070421203551.E82871E4011@bag.python.org> Author: georg.brandl Date: Sat Apr 21 22:35:49 2007 New Revision: 54919 Modified: python/branches/release25-maint/Lib/subprocess.py Log: Bug #1704790: bind name "sys" locally in __del__ method so that it is not cleared before __del__ is run. (backport from rev. 54918) Modified: python/branches/release25-maint/Lib/subprocess.py ============================================================================== --- python/branches/release25-maint/Lib/subprocess.py (original) +++ python/branches/release25-maint/Lib/subprocess.py Sat Apr 21 22:35:49 2007 @@ -628,7 +628,7 @@ return data - def __del__(self): + def __del__(self, sys=sys): if not self._child_created: # We didn't get to successfully create a child process. return From python-checkins at python.org Sun Apr 22 03:19:01 2007 From: python-checkins at python.org (facundo.batista) Date: Sun, 22 Apr 2007 03:19:01 +0200 (CEST) Subject: [Python-checkins] r54920 - python/trunk/Lib/test/test_socket_ssl.py Message-ID: <20070422011901.EB4061E4004@bag.python.org> Author: facundo.batista Date: Sun Apr 22 03:18:56 2007 New Revision: 54920 Modified: python/trunk/Lib/test/test_socket_ssl.py Log: Added tests for other methods of SSL object. Now we cover all the object methods. This is the final step to close the #451607 bug. Modified: python/trunk/Lib/test/test_socket_ssl.py ============================================================================== --- python/trunk/Lib/test/test_socket_ssl.py (original) +++ python/trunk/Lib/test/test_socket_ssl.py Sun Apr 22 03:18:56 2007 @@ -117,6 +117,21 @@ self.assertEqual(i, "Foo\n") s.close() + def testMethods(self): + # read & write is already tried in the Basic test + # now we'll try to get the server info about certificates + # this came from the certificate I used, one I found in /usr/share/openssl + info = "/C=PT/ST=Queensland/L=Lisboa/O=Neuronio, Lda./OU=Desenvolvimento/CN=brutus.neuronio.pt/emailAddress=sampo at iki.fi" + + s = socket.socket() + s.connect(("localhost", 4433)) + ss = socket.ssl(s) + cert = ss.server() + self.assertEqual(cert, info) + cert = ss.issuer() + self.assertEqual(cert, info) + s.close() + class OpenSSLServer(threading.Thread): def __init__(self): From python-checkins at python.org Sun Apr 22 06:34:03 2007 From: python-checkins at python.org (erik.forsberg) Date: Sun, 22 Apr 2007 06:34:03 +0200 (CEST) Subject: [Python-checkins] r54921 - tracker/roundup-src/roundup/cgi/client.py Message-ID: <20070422043403.0C77F1E4005@bag.python.org> Author: erik.forsberg Date: Sun Apr 22 06:34:01 2007 New Revision: 54921 Modified: tracker/roundup-src/roundup/cgi/client.py Log: Rollback when detecting serialization problem in clean_session. See log for r54913. Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Sun Apr 22 06:34:01 2007 @@ -370,6 +370,7 @@ # Another client just updated, and we're running on # serializable isolation. # See http://www.postgresql.org/docs/7.4/interactive/transaction-iso.html + self.db.rollback() return self.db.commit(fail_ok=True) From python-checkins at python.org Sun Apr 22 12:18:47 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Sun, 22 Apr 2007 12:18:47 +0200 (CEST) Subject: [Python-checkins] r54922 - python/branches/release25-maint/Modules/binascii.c Message-ID: <20070422101847.048951E4007@bag.python.org> Author: kristjan.jonsson Date: Sun Apr 22 12:18:46 2007 New Revision: 54922 Modified: python/branches/release25-maint/Modules/binascii.c Log: Properly implement Georg Brandl's Patch #1185447 to the 2.5 maintainance branch Modified: python/branches/release25-maint/Modules/binascii.c ============================================================================== --- python/branches/release25-maint/Modules/binascii.c (original) +++ python/branches/release25-maint/Modules/binascii.c Sun Apr 22 12:18:46 2007 @@ -1160,13 +1160,14 @@ if ((data[in] > 126) || (data[in] == '=') || (header && data[in] == '_') || - ((data[in] == '.') && (linelen == 1)) || + ((data[in] == '.') && (linelen == 0) && + (data[in+1] == '\n' || data[in+1] == '\r' || data[in+1] == 0)) || (!istext && ((data[in] == '\r') || (data[in] == '\n'))) || ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || ((data[in] < 33) && (data[in] != '\r') && (data[in] != '\n') && - (!quotetabs || - (quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) + (quotetabs || + (!quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) { if ((linelen + 3) >= MAXLINESIZE) { linelen = 0; @@ -1231,13 +1232,14 @@ if ((data[in] > 126) || (data[in] == '=') || (header && data[in] == '_') || - ((data[in] == '.') && (linelen == 1)) || + ((data[in] == '.') && (linelen == 0) && + (data[in+1] == '\n' || data[in+1] == '\r' || data[in+1] == 0)) || (!istext && ((data[in] == '\r') || (data[in] == '\n'))) || ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || ((data[in] < 33) && (data[in] != '\r') && (data[in] != '\n') && - (!quotetabs || - (quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) + (quotetabs || + (!quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) { if ((linelen + 3 )>= MAXLINESIZE) { odata[out++] = '='; From nnorwitz at gmail.com Sun Apr 22 20:49:50 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sun, 22 Apr 2007 11:49:50 -0700 Subject: [Python-checkins] r54909 - in python/branches/release25-maint: Modules/_ctypes/callproc.c Modules/binascii.c Modules/cPickle.c Modules/cStringIO.c Modules/posixmodule.c PC/_winreg.c Python/dynload_win.c Python/thread_nt.h In-Reply-To: <20070421124656.ED0081E4003@bag.python.org> References: <20070421124656.ED0081E4003@bag.python.org> Message-ID: This doesn't look like it was applied to the trunk. Most if not all of these cases are still there. n -- On 4/21/07, kristjan.jonsson wrote: > Author: kristjan.jonsson > Date: Sat Apr 21 14:46:49 2007 > New Revision: 54909 > > Modified: > python/branches/release25-maint/Modules/_ctypes/callproc.c > python/branches/release25-maint/Modules/binascii.c > python/branches/release25-maint/Modules/cPickle.c > python/branches/release25-maint/Modules/cStringIO.c > python/branches/release25-maint/Modules/posixmodule.c > python/branches/release25-maint/PC/_winreg.c > python/branches/release25-maint/Python/dynload_win.c > python/branches/release25-maint/Python/thread_nt.h > Log: > Fix various minor issues discovered with static analysis using Visual Studio 2005 Team System. > Removed obsolete comment, since .dll modules are no longer supported on windows, only .pyd. > > Modified: python/branches/release25-maint/Modules/_ctypes/callproc.c > ============================================================================== > --- python/branches/release25-maint/Modules/_ctypes/callproc.c (original) > +++ python/branches/release25-maint/Modules/_ctypes/callproc.c Sat Apr 21 14:46:49 2007 > @@ -64,6 +64,7 @@ > > #ifdef MS_WIN32 > #include > +#include > #else > #include "ctypes_dlfcn.h" > #endif > @@ -97,9 +98,9 @@ > 0, > NULL); > if (n) { > - while (isspace(lpMsgBuf[n-1])) > + while (_istspace(lpMsgBuf[n-1])) > --n; > - lpMsgBuf[n] = '\0'; /* rstrip() */ > + lpMsgBuf[n] = _T('\0'); /* rstrip() */ > } > return lpMsgBuf; > } > > Modified: python/branches/release25-maint/Modules/binascii.c > ============================================================================== > --- python/branches/release25-maint/Modules/binascii.c (original) > +++ python/branches/release25-maint/Modules/binascii.c Sat Apr 21 14:46:49 2007 > @@ -1165,7 +1165,8 @@ > ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || > ((data[in] < 33) && > (data[in] != '\r') && (data[in] != '\n') && > - (quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) > + (!quotetabs || > + (quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) > { > if ((linelen + 3) >= MAXLINESIZE) { > linelen = 0; > @@ -1235,7 +1236,8 @@ > ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || > ((data[in] < 33) && > (data[in] != '\r') && (data[in] != '\n') && > - (quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) > + (!quotetabs || > + (quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) > { > if ((linelen + 3 )>= MAXLINESIZE) { > odata[out++] = '='; > > Modified: python/branches/release25-maint/Modules/cPickle.c > ============================================================================== > --- python/branches/release25-maint/Modules/cPickle.c (original) > +++ python/branches/release25-maint/Modules/cPickle.c Sat Apr 21 14:46:49 2007 > @@ -533,11 +533,12 @@ > self->buf_size = size; > } > else if (n > self->buf_size) { > - self->buf = (char *)realloc(self->buf, n); > - if (!self->buf) { > + char *newbuf = (char *)realloc(self->buf, n); > + if (!newbuf) { > PyErr_NoMemory(); > return -1; > } > + self->buf = newbuf; > self->buf_size = n; > } > > @@ -576,6 +577,7 @@ > i = 0; > while (1) { > int bigger; > + char *newbuf; > for (; i < (self->buf_size - 1); i++) { > if (feof(self->fp) || > (self->buf[i] = getc(self->fp)) == '\n') { > @@ -589,11 +591,12 @@ > PyErr_NoMemory(); > return -1; > } > - self->buf = (char *)realloc(self->buf, bigger); > - if (!self->buf) { > + newbuf = (char *)realloc(self->buf, bigger); > + if (!newbuf) { > PyErr_NoMemory(); > return -1; > } > + self->buf = newbuf; > self->buf_size = bigger; > } > } > @@ -4365,17 +4368,19 @@ > */ > > if ((self->num_marks + 1) >= self->marks_size) { > + int *marks; > s=self->marks_size+20; > if (s <= self->num_marks) s=self->num_marks + 1; > if (self->marks == NULL) > - self->marks=(int *)malloc(s * sizeof(int)); > + marks=(int *)malloc(s * sizeof(int)); > else > - self->marks=(int *)realloc(self->marks, > + marks=(int *)realloc(self->marks, > s * sizeof(int)); > - if (! self->marks) { > + if (!marks) { > PyErr_NoMemory(); > return -1; > } > + self->marks = marks; > self->marks_size = s; > } > > > Modified: python/branches/release25-maint/Modules/cStringIO.c > ============================================================================== > --- python/branches/release25-maint/Modules/cStringIO.c (original) > +++ python/branches/release25-maint/Modules/cStringIO.c Sat Apr 21 14:46:49 2007 > @@ -339,13 +339,17 @@ > } > > if (position > self->buf_size) { > + char *newbuf; > self->buf_size*=2; > if (self->buf_size <= position) self->buf_size=position+1; > - self->buf = (char*) realloc(self->buf,self->buf_size); > - if (!self->buf) { > + newbuf = (char*) realloc(self->buf,self->buf_size); > + if (!newbuf) { > + free(self->buf); > + self->buf = 0; > self->buf_size=self->pos=0; > return PyErr_NoMemory(); > } > + self->buf = newbuf; > } > else if (position < 0) position=0; > > @@ -366,6 +370,7 @@ > O_cwrite(PyObject *self, const char *c, Py_ssize_t l) { > Py_ssize_t newl; > Oobject *oself; > + char *newbuf; > > if (!IO__opencheck(IOOOBJECT(self))) return -1; > oself = (Oobject *)self; > @@ -377,12 +382,15 @@ > assert(newl + 1 < INT_MAX); > oself->buf_size = (int)(newl+1); > } > - oself->buf = (char*)realloc(oself->buf, oself->buf_size); > - if (!oself->buf) { > + newbuf = (char*)realloc(oself->buf, oself->buf_size); > + if (!newbuf) { > PyErr_SetString(PyExc_MemoryError,"out of memory"); > + free(oself->buf); > + oself->buf = 0; > oself->buf_size = oself->pos = 0; > return -1; > } > + oself->buf = newbuf; > } > > memcpy(oself->buf+oself->pos,c,l); > > Modified: python/branches/release25-maint/Modules/posixmodule.c > ============================================================================== > --- python/branches/release25-maint/Modules/posixmodule.c (original) > +++ python/branches/release25-maint/Modules/posixmodule.c Sat Apr 21 14:46:49 2007 > @@ -4788,18 +4788,19 @@ > (sizeof(modulepath)/sizeof(modulepath[0])) > -strlen(modulepath)); > if (stat(modulepath, &statinfo) != 0) { > + size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]); > /* Eeek - file-not-found - possibly an embedding > situation - see if we can locate it in sys.prefix > */ > strncpy(modulepath, > Py_GetExecPrefix(), > - sizeof(modulepath)/sizeof(modulepath[0])); > + mplen); > + modulepath[mplen-1] = '\0'; > if (modulepath[strlen(modulepath)-1] != '\\') > strcat(modulepath, "\\"); > strncat(modulepath, > szConsoleSpawn, > - (sizeof(modulepath)/sizeof(modulepath[0])) > - -strlen(modulepath)); > + mplen-strlen(modulepath)); > /* No where else to look - raise an easily identifiable > error, rather than leaving Windows to report > "file not found" - as the user is probably blissfully > > Modified: python/branches/release25-maint/PC/_winreg.c > ============================================================================== > --- python/branches/release25-maint/PC/_winreg.c (original) > +++ python/branches/release25-maint/PC/_winreg.c Sat Apr 21 14:46:49 2007 > @@ -699,7 +699,7 @@ > case REG_DWORD: > if (value != Py_None && !PyInt_Check(value)) > return FALSE; > - *retDataBuf = (BYTE *)PyMem_NEW(DWORD, sizeof(DWORD)); > + *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1); > if (*retDataBuf==NULL){ > PyErr_NoMemory(); > return FALSE; > > Modified: python/branches/release25-maint/Python/dynload_win.c > ============================================================================== > --- python/branches/release25-maint/Python/dynload_win.c (original) > +++ python/branches/release25-maint/Python/dynload_win.c Sat Apr 21 14:46:49 2007 > @@ -13,16 +13,8 @@ > const struct filedescr _PyImport_DynLoadFiletab[] = { > #ifdef _DEBUG > {"_d.pyd", "rb", C_EXTENSION}, > - /* Temporarily disable .dll, to avoid conflicts between sqlite3.dll > - and the sqlite3 package. If this needs to be reverted for 2.5, > - some other solution for the naming conflict must be found. > - {"_d.dll", "rb", C_EXTENSION}, > - */ > #else > {".pyd", "rb", C_EXTENSION}, > - /* Likewise > - {".dll", "rb", C_EXTENSION}, > - */ > #endif > {0, 0} > }; > > Modified: python/branches/release25-maint/Python/thread_nt.h > ============================================================================== > --- python/branches/release25-maint/Python/thread_nt.h (original) > +++ python/branches/release25-maint/Python/thread_nt.h Sat Apr 21 14:46:49 2007 > @@ -202,12 +202,12 @@ > * too many threads". > */ > dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n", > - PyThread_get_thread_ident(), rv, errno)); > + PyThread_get_thread_ident(), (void*)rv, errno)); > obj.id = -1; > } > else { > dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", > - PyThread_get_thread_ident(), rv)); > + PyThread_get_thread_ident(), (void*)rv)); > /* wait for thread to initialize, so we can get its id */ > WaitForSingleObject(obj.done, INFINITE); > assert(obj.id != -1); > @@ -333,7 +333,7 @@ > dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); > > if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) > - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); > + dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError())); > } > > /* minimum/maximum thread stack sizes supported */ > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > From kristjan at ccpgames.com Sun Apr 22 21:49:28 2007 From: kristjan at ccpgames.com (=?iso-8859-1?Q?Kristj=E1n_Valur_J=F3nsson?=) Date: Sun, 22 Apr 2007 19:49:28 +0000 Subject: [Python-checkins] r54909 - in python/branches/release25-maint: Modules/_ctypes/callproc.c Modules/binascii.c Modules/cPickle.c Modules/cStringIO.c Modules/posixmodule.c PC/_winreg.c Python/dynload_win.c Python/thread_nt.h In-Reply-To: References: <20070421124656.ED0081E4003@bag.python.org> Message-ID: <4E9372E6B2234D4F859320D896059A9508C00CE1A5@exchis.ccp.ad.local> True, this was the result of work I was doing for CCP when integrating 2.5. I plan to do do a fresh check of the trunk in the next few days. Kristj?n -----Original Message----- From: Neal Norwitz [mailto:nnorwitz at gmail.com] Sent: Sunday, April 22, 2007 18:50 To: kristjan.jonsson; Kristj?n Valur J?nsson Subject: Re: [Python-checkins] r54909 - in python/branches/release25-maint: Modules/_ctypes/callproc.c Modules/binascii.c Modules/cPickle.c Modules/cStringIO.c Modules/posixmodule.c PC/_winreg.c Python/dynload_win.c Python/thread_nt.h This doesn't look like it was applied to the trunk. Most if not all of these cases are still there. n -- On 4/21/07, kristjan.jonsson wrote: > Author: kristjan.jonsson > Date: Sat Apr 21 14:46:49 2007 > New Revision: 54909 > > Modified: > python/branches/release25-maint/Modules/_ctypes/callproc.c > python/branches/release25-maint/Modules/binascii.c > python/branches/release25-maint/Modules/cPickle.c > python/branches/release25-maint/Modules/cStringIO.c > python/branches/release25-maint/Modules/posixmodule.c > python/branches/release25-maint/PC/_winreg.c > python/branches/release25-maint/Python/dynload_win.c > python/branches/release25-maint/Python/thread_nt.h > Log: > Fix various minor issues discovered with static analysis using Visual Studio 2005 Team System. > Removed obsolete comment, since .dll modules are no longer supported on windows, only .pyd. > > Modified: python/branches/release25-maint/Modules/_ctypes/callproc.c > ============================================================================== > --- python/branches/release25-maint/Modules/_ctypes/callproc.c (original) > +++ python/branches/release25-maint/Modules/_ctypes/callproc.c Sat Apr 21 14:46:49 2007 > @@ -64,6 +64,7 @@ > > #ifdef MS_WIN32 > #include > +#include > #else > #include "ctypes_dlfcn.h" > #endif > @@ -97,9 +98,9 @@ > 0, > NULL); > if (n) { > - while (isspace(lpMsgBuf[n-1])) > + while (_istspace(lpMsgBuf[n-1])) > --n; > - lpMsgBuf[n] = '\0'; /* rstrip() */ > + lpMsgBuf[n] = _T('\0'); /* rstrip() */ > } > return lpMsgBuf; > } > > Modified: python/branches/release25-maint/Modules/binascii.c > ============================================================================== > --- python/branches/release25-maint/Modules/binascii.c (original) > +++ python/branches/release25-maint/Modules/binascii.c Sat Apr 21 14:46:49 2007 > @@ -1165,7 +1165,8 @@ > ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || > ((data[in] < 33) && > (data[in] != '\r') && (data[in] != '\n') && > - (quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) > + (!quotetabs || > + (quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) > { > if ((linelen + 3) >= MAXLINESIZE) { > linelen = 0; > @@ -1235,7 +1236,8 @@ > ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || > ((data[in] < 33) && > (data[in] != '\r') && (data[in] != '\n') && > - (quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) > + (!quotetabs || > + (quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) > { > if ((linelen + 3 )>= MAXLINESIZE) { > odata[out++] = '='; > > Modified: python/branches/release25-maint/Modules/cPickle.c > ============================================================================== > --- python/branches/release25-maint/Modules/cPickle.c (original) > +++ python/branches/release25-maint/Modules/cPickle.c Sat Apr 21 14:46:49 2007 > @@ -533,11 +533,12 @@ > self->buf_size = size; > } > else if (n > self->buf_size) { > - self->buf = (char *)realloc(self->buf, n); > - if (!self->buf) { > + char *newbuf = (char *)realloc(self->buf, n); > + if (!newbuf) { > PyErr_NoMemory(); > return -1; > } > + self->buf = newbuf; > self->buf_size = n; > } > > @@ -576,6 +577,7 @@ > i = 0; > while (1) { > int bigger; > + char *newbuf; > for (; i < (self->buf_size - 1); i++) { > if (feof(self->fp) || > (self->buf[i] = getc(self->fp)) == '\n') { > @@ -589,11 +591,12 @@ > PyErr_NoMemory(); > return -1; > } > - self->buf = (char *)realloc(self->buf, bigger); > - if (!self->buf) { > + newbuf = (char *)realloc(self->buf, bigger); > + if (!newbuf) { > PyErr_NoMemory(); > return -1; > } > + self->buf = newbuf; > self->buf_size = bigger; > } > } > @@ -4365,17 +4368,19 @@ > */ > > if ((self->num_marks + 1) >= self->marks_size) { > + int *marks; > s=self->marks_size+20; > if (s <= self->num_marks) s=self->num_marks + 1; > if (self->marks == NULL) > - self->marks=(int *)malloc(s * sizeof(int)); > + marks=(int *)malloc(s * sizeof(int)); > else > - self->marks=(int *)realloc(self->marks, > + marks=(int *)realloc(self->marks, > s * sizeof(int)); > - if (! self->marks) { > + if (!marks) { > PyErr_NoMemory(); > return -1; > } > + self->marks = marks; > self->marks_size = s; > } > > > Modified: python/branches/release25-maint/Modules/cStringIO.c > ============================================================================== > --- python/branches/release25-maint/Modules/cStringIO.c (original) > +++ python/branches/release25-maint/Modules/cStringIO.c Sat Apr 21 14:46:49 2007 > @@ -339,13 +339,17 @@ > } > > if (position > self->buf_size) { > + char *newbuf; > self->buf_size*=2; > if (self->buf_size <= position) self->buf_size=position+1; > - self->buf = (char*) realloc(self->buf,self->buf_size); > - if (!self->buf) { > + newbuf = (char*) realloc(self->buf,self->buf_size); > + if (!newbuf) { > + free(self->buf); > + self->buf = 0; > self->buf_size=self->pos=0; > return PyErr_NoMemory(); > } > + self->buf = newbuf; > } > else if (position < 0) position=0; > > @@ -366,6 +370,7 @@ > O_cwrite(PyObject *self, const char *c, Py_ssize_t l) { > Py_ssize_t newl; > Oobject *oself; > + char *newbuf; > > if (!IO__opencheck(IOOOBJECT(self))) return -1; > oself = (Oobject *)self; > @@ -377,12 +382,15 @@ > assert(newl + 1 < INT_MAX); > oself->buf_size = (int)(newl+1); > } > - oself->buf = (char*)realloc(oself->buf, oself->buf_size); > - if (!oself->buf) { > + newbuf = (char*)realloc(oself->buf, oself->buf_size); > + if (!newbuf) { > PyErr_SetString(PyExc_MemoryError,"out of memory"); > + free(oself->buf); > + oself->buf = 0; > oself->buf_size = oself->pos = 0; > return -1; > } > + oself->buf = newbuf; > } > > memcpy(oself->buf+oself->pos,c,l); > > Modified: python/branches/release25-maint/Modules/posixmodule.c > ============================================================================== > --- python/branches/release25-maint/Modules/posixmodule.c (original) > +++ python/branches/release25-maint/Modules/posixmodule.c Sat Apr 21 14:46:49 2007 > @@ -4788,18 +4788,19 @@ > (sizeof(modulepath)/sizeof(modulepath[0])) > -strlen(modulepath)); > if (stat(modulepath, &statinfo) != 0) { > + size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]); > /* Eeek - file-not-found - possibly an embedding > situation - see if we can locate it in sys.prefix > */ > strncpy(modulepath, > Py_GetExecPrefix(), > - sizeof(modulepath)/sizeof(modulepath[0])); > + mplen); > + modulepath[mplen-1] = '\0'; > if (modulepath[strlen(modulepath)-1] != '\\') > strcat(modulepath, "\\"); > strncat(modulepath, > szConsoleSpawn, > - (sizeof(modulepath)/sizeof(modulepath[0])) > - -strlen(modulepath)); > + mplen-strlen(modulepath)); > /* No where else to look - raise an easily identifiable > error, rather than leaving Windows to report > "file not found" - as the user is probably blissfully > > Modified: python/branches/release25-maint/PC/_winreg.c > ============================================================================== > --- python/branches/release25-maint/PC/_winreg.c (original) > +++ python/branches/release25-maint/PC/_winreg.c Sat Apr 21 14:46:49 2007 > @@ -699,7 +699,7 @@ > case REG_DWORD: > if (value != Py_None && !PyInt_Check(value)) > return FALSE; > - *retDataBuf = (BYTE *)PyMem_NEW(DWORD, sizeof(DWORD)); > + *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1); > if (*retDataBuf==NULL){ > PyErr_NoMemory(); > return FALSE; > > Modified: python/branches/release25-maint/Python/dynload_win.c > ============================================================================== > --- python/branches/release25-maint/Python/dynload_win.c (original) > +++ python/branches/release25-maint/Python/dynload_win.c Sat Apr 21 14:46:49 2007 > @@ -13,16 +13,8 @@ > const struct filedescr _PyImport_DynLoadFiletab[] = { > #ifdef _DEBUG > {"_d.pyd", "rb", C_EXTENSION}, > - /* Temporarily disable .dll, to avoid conflicts between sqlite3.dll > - and the sqlite3 package. If this needs to be reverted for 2.5, > - some other solution for the naming conflict must be found. > - {"_d.dll", "rb", C_EXTENSION}, > - */ > #else > {".pyd", "rb", C_EXTENSION}, > - /* Likewise > - {".dll", "rb", C_EXTENSION}, > - */ > #endif > {0, 0} > }; > > Modified: python/branches/release25-maint/Python/thread_nt.h > ============================================================================== > --- python/branches/release25-maint/Python/thread_nt.h (original) > +++ python/branches/release25-maint/Python/thread_nt.h Sat Apr 21 14:46:49 2007 > @@ -202,12 +202,12 @@ > * too many threads". > */ > dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n", > - PyThread_get_thread_ident(), rv, errno)); > + PyThread_get_thread_ident(), (void*)rv, errno)); > obj.id = -1; > } > else { > dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", > - PyThread_get_thread_ident(), rv)); > + PyThread_get_thread_ident(), (void*)rv)); > /* wait for thread to initialize, so we can get its id */ > WaitForSingleObject(obj.done, INFINITE); > assert(obj.id != -1); > @@ -333,7 +333,7 @@ > dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); > > if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) > - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); > + dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError())); > } > > /* minimum/maximum thread stack sizes supported */ > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > From python-checkins at python.org Mon Apr 23 03:29:51 2007 From: python-checkins at python.org (neal.norwitz) Date: Mon, 23 Apr 2007 03:29:51 +0200 (CEST) Subject: [Python-checkins] r54923 - peps/trunk/pep-0361.txt Message-ID: <20070423012951.236D31E4007@bag.python.org> Author: neal.norwitz Date: Mon Apr 23 03:29:47 2007 New Revision: 54923 Modified: peps/trunk/pep-0361.txt Log: Various status updates Modified: peps/trunk/pep-0361.txt ============================================================================== --- peps/trunk/pep-0361.txt (original) +++ peps/trunk/pep-0361.txt Mon Apr 23 03:29:47 2007 @@ -51,16 +51,22 @@ PEPs: - None + 352: Raising a string exception now triggers a TypeError. + Attempting to catch a string exception raises DeprecationWarning. New modules in the standard library: None - Other major features: + Python 3.0 compatability: None + Other major features: + + - with/as will be keywords + - a __dir__() special method to control dir() was added [1] + Possible features for 2.6 @@ -70,7 +76,6 @@ The following PEPs are being worked on for possible inclusion in 2.6: - - PEP 275: Switching on Multiple Values - PEP 297: Support for System Upgrades Each non-trivial feature listed here that is not a PEP must be @@ -78,7 +83,6 @@ - distutils replacement (requires a PEP) - turtle.py replacement or enhancements - - adding a __dir__() magic method to control dir() [1] New modules in the standard library: @@ -86,6 +90,8 @@ http://python.org/sf/1505257 (Owner: MAL) + - JSON implementation + - setuptools BDFL pronouncement for inclusion in 2.5: http://mail.python.org/pipermail/python-dev/2006-April/063964.html @@ -116,16 +122,14 @@ * file.xreadlines * function attributes that start with func_* (should use __*__) * softspace removal for print() function - * the L prefix for long literals - * removal of the sets module + * the L suffix for long literals + * removal of the sets and exceptions module * renaming of __nonzero__ to __bool__ * multiple inheritance with classic classes? (MRO might change) * properties and classic classes? (instance attrs shadow property) - use __bool__ method if available and there's no __nonzero__ - - with/as will be keywords - - Check the various bits of code in Demo/ and Tools/ all still work, update or remove the ones that don't. @@ -153,7 +157,6 @@ - Remove the fpectl module? - - Make everything in Modules/ build cleanly with g++ Deferred until 2.7 @@ -177,6 +180,7 @@ [1] Adding a __dir__() magic method http://mail.python.org/pipermail/python-dev/2006-July/067139.html + Copyright This document has been placed in the public domain. From python-checkins at python.org Mon Apr 23 03:58:36 2007 From: python-checkins at python.org (barry.warsaw) Date: Mon, 23 Apr 2007 03:58:36 +0200 (CEST) Subject: [Python-checkins] r54924 - in python/branches/release25-maint: Lib/test/test_pty.py Misc/NEWS Message-ID: <20070423015836.503731E4007@bag.python.org> Author: barry.warsaw Date: Mon Apr 23 03:58:33 2007 New Revision: 54924 Modified: python/branches/release25-maint/Lib/test/test_pty.py python/branches/release25-maint/Misc/NEWS Log: Recommit r54805: Add code to read from master_fd in the parent, breaking when we get an OSError (EIO can occur on Linux) or there's no more data to read. Without this, test_pty.py can hang on the waitpid() because the child is blocking on the stdout write. This will definitely happen on Mac OS X and could potentially happen on other platforms. See the comment for details. Modified: python/branches/release25-maint/Lib/test/test_pty.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_pty.py (original) +++ python/branches/release25-maint/Lib/test/test_pty.py Mon Apr 23 03:58:33 2007 @@ -115,6 +115,24 @@ os._exit(4) else: debug("Waiting for child (%d) to finish."%pid) + # In verbose mode, we have to consume the debug output from the child or + # the child will block, causing this test to hang in the parent's + # waitpid() call. The child blocks after a platform-dependent amount of + # data is written to its fd. On Linux 2.6, it's 4000 bytes and the child + # won't block, but on OS X even the small writes in the child above will + # block it. Also on Linux, the read() will throw an OSError (input/output + # error) when it tries to read past the end of the buffer but the child's + # already exited, so catch and discard those exceptions. It's not worth + # checking for EIO. + while True: + try: + data = os.read(master_fd, 80) + except OSError: + break + if not data: + break + sys.stdout.write(data.replace('\r\n', '\n')) + ##line = os.read(master_fd, 80) ##lines = line.replace('\r\n', '\n').split('\n') ##if False and lines != ['In child, calling os.setsid()', Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Mon Apr 23 03:58:33 2007 @@ -17,6 +17,9 @@ - tarfile.py: Fix directory names to have only one trailing slash. +- Fix test_pty.py to not hang on OS X (and theoretically other *nixes) when + run in verbose mode. + What's New in Python 2.5.1? ============================= From python-checkins at python.org Mon Apr 23 19:08:36 2007 From: python-checkins at python.org (facundo.batista) Date: Mon, 23 Apr 2007 19:08:36 +0200 (CEST) Subject: [Python-checkins] r54927 - in python/trunk/Lib: test/test_urllib2.py urllib2.py Message-ID: <20070423170836.5BE601E4017@bag.python.org> Author: facundo.batista Date: Mon Apr 23 19:08:31 2007 New Revision: 54927 Modified: python/trunk/Lib/test/test_urllib2.py python/trunk/Lib/urllib2.py Log: As specified in RFC 2616, 2xx code indicates that the client's request was successfully received, understood, and accepted. Now in these cases no error is raised. Also fixed tests. Modified: python/trunk/Lib/test/test_urllib2.py ============================================================================== --- python/trunk/Lib/test/test_urllib2.py (original) +++ python/trunk/Lib/test/test_urllib2.py Mon Apr 23 19:08:31 2007 @@ -766,16 +766,24 @@ url = "http://example.com/" req = Request(url) - # 200 OK is passed through + # all 2xx are passed through r = MockResponse(200, "OK", {}, "", url) newr = h.http_response(req, r) self.assert_(r is newr) self.assert_(not hasattr(o, "proto")) # o.error not called + r = MockResponse(202, "Accepted", {}, "", url) + newr = h.http_response(req, r) + self.assert_(r is newr) + self.assert_(not hasattr(o, "proto")) # o.error not called + r = MockResponse(206, "Partial content", {}, "", url) + newr = h.http_response(req, r) + self.assert_(r is newr) + self.assert_(not hasattr(o, "proto")) # o.error not called # anything else calls o.error (and MockOpener returns None, here) - r = MockResponse(201, "Created", {}, "", url) + r = MockResponse(502, "Bad gateway", {}, "", url) self.assert_(h.http_response(req, r) is None) self.assertEqual(o.proto, "http") # o.error called - self.assertEqual(o.args, (req, r, 201, "Created", {})) + self.assertEqual(o.args, (req, r, 502, "Bad gateway", {})) def test_cookies(self): cj = MockCookieJar() Modified: python/trunk/Lib/urllib2.py ============================================================================== --- python/trunk/Lib/urllib2.py (original) +++ python/trunk/Lib/urllib2.py Mon Apr 23 19:08:31 2007 @@ -487,7 +487,9 @@ def http_response(self, request, response): code, msg, hdrs = response.code, response.msg, response.info() - if code not in (200, 206): + # According to RFC 2616, "2xx" code indicates that the client's + # request was successfully received, understood, and accepted. + if not (200 <= code < 300): response = self.parent.error( 'http', request, response, code, msg, hdrs) From buildbot at python.org Mon Apr 23 20:59:24 2007 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Apr 2007 18:59:24 +0000 Subject: [Python-checkins] buildbot warnings in alpha Debian trunk Message-ID: <20070423185925.42F271E4007@bag.python.org> The Buildbot has detected a new failure of alpha Debian trunk. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Debian%2520trunk/builds/9 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: facundo.batista Build had warnings: warnings test Excerpt from the test logfile: 2 tests failed: test_socket_ssl test_urllib2 ====================================================================== ERROR: testTimeout (test.test_socket_ssl.ConnectedTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-alpha/build/Lib/test/test_socket_ssl.py", line 52, in testTimeout s.connect(ADDR) File "", line 1, in connect gaierror: (-2, 'Name or service not known') ====================================================================== ERROR: test_file (test.test_urllib2.HandlerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-alpha/build/Lib/test/test_urllib2.py", line 643, in test_file h.file_open, Request(url)) File "/home/pybot/buildarea/trunk.klose-debian-alpha/build/Lib/unittest.py", line 329, in failUnlessRaises callableObj(*args, **kwargs) File "/home/pybot/buildarea/trunk.klose-debian-alpha/build/Lib/urllib2.py", line 1199, in file_open return self.open_local_file(req) File "/home/pybot/buildarea/trunk.klose-debian-alpha/build/Lib/urllib2.py", line 1230, in open_local_file (not port and socket.gethostbyname(host) in self.get_names()): gaierror: (-2, 'Name or service not known') make: *** [buildbottest] Error 1 sincerely, -The Buildbot From gki at pldtdsl.net Sat Apr 21 19:39:05 2007 From: gki at pldtdsl.net (Global Knowledge PH) Date: Sun, 22 Apr 2007 01:39:05 +0800 Subject: [Python-checkins] National Security Summit in Boracay on May 30-31, 2007 Message-ID: <6cf6601c7843b$f4fdd040$2a01a8c0@gk0bcb4128deb6> 1st National Security Summit In BORACAY May 30 - 31, 2007 Wednesday - Thursday | 9am-5pm | Fee: P5,995 / participant BORACAY, Philippines | Disaster Recovery | Licensed Penetration Tester | | CEH / CHFI | E - Business Security | * Fee includes Food (Complete meals for 2 days) * Accommodation for 2 days and 1 night * * Receive 4 Seminar Manuals & Training Kit * Receive 4 Seminar Certificates of Completion * "Corporate giveaways" " Chance to win FREE training" Global Knowledge Associates and its IT security partners are holding 2-day "1st National Security Summit in Boracay 2007" seminar. The seminar will cover 4-in-1 security seminar on: 1. Disaster Recovery (ICT) 2. Licensed Penetration Tester 3. CEH / CHFI 4. E - Business Security DISASTER RECOVERY (ICT) This seminar gives an overview of the methods in identifying vulnerabilities and takes appropriate countermeasures to prevent and mitigate failure risks for an organization. It also prepares the networking professional with an idea regarding disaster recovery principles, including preparation of a disaster recovery plan, assessment of risks in the enterprise, development of policies, and procedures, and understanding of the roles and relationships of various members of an organization, implementation of the plan, and recovering from a disaster. This seminar gives an overview of an enterprise-wide approach to developing a disaster recovery plan. Students will learn how to create a secure network by putting policies and procedures in place, and how to restore a network in the event of a disaster. This seminar will prepare students for the formal 3-day course. LICENSED PENETRATION TESTER (LPT) This seminar gives an overview of the LPT Certification which was designed to recognize mastery of international standard of penetration testing and understanding of a Common Body of Knowledge. This seminar will discuss topics on: ? Overview of Penetration Testing Methodologies ? Overview of Penetration Testing Planning and Scheduling ? Overview of Information Gathering ? Overview of Vulnerability Analysis ? Overview of External Penetration Testing ? Overview of Physical Security Penetration Testing CEH / CHFI The CEH seminar will introduce the students an environment where they will be shown an overview of how to scan, test, hack, and secure their own systems. Students will begin by understanding how perimeter defenses work and then be lead into scanning and attacking their own networks, no real network is harmed. Students will also be introduced to topics on Intrusion Detection, Policy Creation, Social Engineering, etc. This seminar is in preparation for the intensive 5 day of hands-on Ethical Hacking (CEH class). The CHFI seminar will give participants an overview of the necessary skills to identify an intruder's footprints and to properly gather the necessary evidence to prosecute. Many of today's top tools of the forensic trade will be introduced during this seminar. The need for businesses to become more efficient and integrated with one another, as well as the home user, has given way to a new type of criminal, the "cyber-criminal." It is no longer a matter of "will your organization be comprised (hacked)?" but, rather, "when?" Today's battles between corporations, governments, and countries are no longer fought only in the typical arenas of boardrooms or battlefields using physical force. Now the battlefield starts in the technical realm, which ties into most every facet of modern day life. If you or your organization requires an overview of the knowledge or skills to identify, track, and prosecute the cyber-criminal, then this is the seminar for you. This seminar is your preparation to a 5-day formal CHFI class. E-BUSINESS SECURITY In this seminar you will explore the security technique fundamentals involved in minimizing E-Business security risks. This will give an overview of the concepts such as securing Web clients, servers, and communications. REGISTER NOW! GLOBAL KNOWLEDGE ASSOCIATES, INC. To Register: Call (632) 683-0969 / 637-3657/ 0921532-8150 Or, visit us at 2502B West Tower, PSE Bldg. Exchange Road, Ortigas Center, Pasig City, Philippines 1600 Email: sandra at globalknowledgeph.com; sandramedalla at gmail.com ; Sandra_medalla at yahoo.com URL: www.globalknowledgeph.com _____ If you want to unsubscribe from this mailing list. Please Click it -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/python-checkins/attachments/20070422/fe42f10a/attachment.htm From python-checkins at python.org Tue Apr 24 01:37:34 2007 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 24 Apr 2007 01:37:34 +0200 (CEST) Subject: [Python-checkins] r54928 - peps/trunk/pep-3119.txt Message-ID: <20070423233734.CB9801E4007@bag.python.org> Author: guido.van.rossum Date: Tue Apr 24 01:37:29 2007 New Revision: 54928 Modified: peps/trunk/pep-3119.txt Log: Add some text that Talin suggested. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Tue Apr 24 01:37:29 2007 @@ -101,9 +101,19 @@ done using isinstance(), and the presence of a particular ABC means that the test has passed. +In addition, the ABCs define a minimal set of methods that establish +the characteristic behavior of the type. Code that discriminates +objects based on their ABC type can trust that those methods will +always be present. Each of these methods are accompanied by an +generalized abstract semantic definition that is described in the +documentation for the ABC. These standard semantic definitions are +not enforced, but are strongly recommended. + Like all other things in Python, these promises are in the nature of a -gentlemen's agreement - which means that the language does not attempt -to enforce that these promises are kept. +gentlemen's agreement, which in this case means that while the +language does enforce some of the promises made in the ABC, it is up +to the implementer of the concrete class to insure that the remaining +ones are kept. Specification @@ -150,7 +160,7 @@ The exception raised when attempting to instantiate an abstract class. It derives from ``TypeError``. -**Open issues:** +**Open issues:** * Implementing the prohibition on instantiation may weigh down instance creation of popular built-in classes like ``tuple`` or From nnorwitz at gmail.com Tue Apr 24 05:32:00 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Mon, 23 Apr 2007 20:32:00 -0700 Subject: [Python-checkins] r54927 - in python/trunk/Lib: test/test_urllib2.py urllib2.py In-Reply-To: <20070423170836.5BE601E4017@bag.python.org> References: <20070423170836.5BE601E4017@bag.python.org> Message-ID: On 4/23/07, facundo.batista wrote: > Author: facundo.batista > Date: Mon Apr 23 19:08:31 2007 > New Revision: 54927 > > Modified: > python/trunk/Lib/test/test_urllib2.py > python/trunk/Lib/urllib2.py > Log: > > As specified in RFC 2616, 2xx code indicates that the client's > request was successfully received, understood, and accepted. > Now in these cases no error is raised. Also fixed tests. Facundo, Can you add a note to Misc/NEWS about this? Also, should this be backported? n From python-checkins at python.org Tue Apr 24 05:43:55 2007 From: python-checkins at python.org (collin.winter) Date: Tue, 24 Apr 2007 05:43:55 +0200 (CEST) Subject: [Python-checkins] r54929 - python/trunk/Lib/test/README Message-ID: <20070424034355.CCD091E400E@bag.python.org> Author: collin.winter Date: Tue Apr 24 05:43:46 2007 New Revision: 54929 Modified: python/trunk/Lib/test/README Log: Convert PyUnit -> unittest. Modified: python/trunk/Lib/test/README ============================================================================== --- python/trunk/Lib/test/README (original) +++ python/trunk/Lib/test/README Tue Apr 24 05:43:46 2007 @@ -15,7 +15,7 @@ one of these options. Each option requires writing a test module using the conventions of the selected option: - - PyUnit_ based tests + - unittest_ based tests - doctest_ based tests - "traditional" Python test modules @@ -28,27 +28,26 @@ able to refer to the C and Python code in the CVS repository when writing your regression test cases. -.. _PyUnit: .. _unittest: http://www.python.org/doc/current/lib/module-unittest.html .. _doctest: http://www.python.org/doc/current/lib/module-doctest.html -PyUnit based tests +unittest-based tests ------------------ -The PyUnit_ framework is based on the ideas of unit testing as espoused +The unittest_ framework is based on the ideas of unit testing as espoused by Kent Beck and the `Extreme Programming`_ (XP) movement. The specific interface provided by the framework is tightly based on the JUnit_ Java implementation of Beck's original SmallTalk test framework. Please see the documentation of the unittest_ module for detailed information on -the interface and general guidelines on writing PyUnit based tests. +the interface and general guidelines on writing unittest-based tests. The test_support helper module provides two functions for use by -PyUnit based tests in the Python regression testing framework: +unittest-based tests in the Python regression testing framework: -- ``run_unittest()`` takes a ``unittest.TestCase`` derived class as a - parameter and runs the tests defined in that class +- ``run_unittest()`` takes a number of ``unittest.TestCase`` derived classes as + parameters and runs the tests defined in those classes. - ``run_suite()`` takes a populated ``TestSuite`` instance and runs the - tests + tests. ``run_suite()`` is preferred because unittest files typically grow multiple test classes, and you might as well be prepared. @@ -63,7 +62,7 @@ latter information makes it easier to find the source for the test than the docstring. -All PyUnit-based tests in the Python test suite use boilerplate that +All unittest-based tests in the Python test suite use boilerplate that looks like this (with minor variations):: import unittest @@ -415,7 +414,7 @@ This is rarely required with the "traditional" Python tests, and you shouldn't create a module global with name test_main unless you're specifically exploiting this gimmick. This usage does - prove useful with PyUnit-based tests as well, however; defining + prove useful with unittest-based tests as well, however; defining a ``test_main()`` which is run by regrtest and a script-stub in the test module ("``if __name__ == '__main__': test_main()``") allows the test to be used like any other Python test and also work From python-checkins at python.org Tue Apr 24 05:52:16 2007 From: python-checkins at python.org (collin.winter) Date: Tue, 24 Apr 2007 05:52:16 +0200 (CEST) Subject: [Python-checkins] r54930 - python/branches/release25-maint/Lib/test/README Message-ID: <20070424035216.6A0831E4011@bag.python.org> Author: collin.winter Date: Tue Apr 24 05:52:08 2007 New Revision: 54930 Modified: python/branches/release25-maint/Lib/test/README Log: Convert PyUnit -> unittest. Backported from r54929. Modified: python/branches/release25-maint/Lib/test/README ============================================================================== --- python/branches/release25-maint/Lib/test/README (original) +++ python/branches/release25-maint/Lib/test/README Tue Apr 24 05:52:08 2007 @@ -15,7 +15,7 @@ one of these options. Each option requires writing a test module using the conventions of the selected option: - - PyUnit_ based tests + - unittest_ based tests - doctest_ based tests - "traditional" Python test modules @@ -28,27 +28,26 @@ able to refer to the C and Python code in the CVS repository when writing your regression test cases. -.. _PyUnit: .. _unittest: http://www.python.org/doc/current/lib/module-unittest.html .. _doctest: http://www.python.org/doc/current/lib/module-doctest.html -PyUnit based tests +unittest-based tests ------------------ -The PyUnit_ framework is based on the ideas of unit testing as espoused +The unittest_ framework is based on the ideas of unit testing as espoused by Kent Beck and the `Extreme Programming`_ (XP) movement. The specific interface provided by the framework is tightly based on the JUnit_ Java implementation of Beck's original SmallTalk test framework. Please see the documentation of the unittest_ module for detailed information on -the interface and general guidelines on writing PyUnit based tests. +the interface and general guidelines on writing unittest-based tests. The test_support helper module provides two functions for use by -PyUnit based tests in the Python regression testing framework: +unittest-based tests in the Python regression testing framework: -- ``run_unittest()`` takes a ``unittest.TestCase`` derived class as a - parameter and runs the tests defined in that class +- ``run_unittest()`` takes a number of ``unittest.TestCase`` derived class as + parameters and runs the tests defined in those classes. - ``run_suite()`` takes a populated ``TestSuite`` instance and runs the - tests + tests. ``run_suite()`` is preferred because unittest files typically grow multiple test classes, and you might as well be prepared. @@ -63,7 +62,7 @@ latter information makes it easier to find the source for the test than the docstring. -All PyUnit-based tests in the Python test suite use boilerplate that +All unittest-based tests in the Python test suite use boilerplate that looks like this (with minor variations):: import unittest @@ -415,7 +414,7 @@ This is rarely required with the "traditional" Python tests, and you shouldn't create a module global with name test_main unless you're specifically exploiting this gimmick. This usage does - prove useful with PyUnit-based tests as well, however; defining + prove useful with unittest-based tests as well, however; defining a ``test_main()`` which is run by regrtest and a script-stub in the test module ("``if __name__ == '__main__': test_main()``") allows the test to be used like any other Python test and also work From buildbot at python.org Tue Apr 24 05:53:58 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Apr 2007 03:53:58 +0000 Subject: [Python-checkins] buildbot failure in x86 XP trunk Message-ID: <20070424035358.DD6D91E400A@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/388 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Tue Apr 24 06:10:08 2007 From: python-checkins at python.org (collin.winter) Date: Tue, 24 Apr 2007 06:10:08 +0200 (CEST) Subject: [Python-checkins] r54931 - python/trunk/Lib/test/test_zlib.py Message-ID: <20070424041008.6DA771E400A@bag.python.org> Author: collin.winter Date: Tue Apr 24 06:09:52 2007 New Revision: 54931 Modified: python/trunk/Lib/test/test_zlib.py Log: Remove code that hasn't been called in years. Modified: python/trunk/Lib/test/test_zlib.py ============================================================================== --- python/trunk/Lib/test/test_zlib.py (original) +++ python/trunk/Lib/test/test_zlib.py Tue Apr 24 06:09:52 2007 @@ -3,22 +3,6 @@ import zlib import random -# print test_support.TESTFN - -def getbuf(): - # This was in the original. Avoid non-repeatable sources. - # Left here (unused) in case something wants to be done with it. - import imp - try: - t = imp.find_module('test_zlib') - file = t[0] - except ImportError: - file = open(__file__) - buf = file.read() * 8 - file.close() - return buf - - class ChecksumTestCase(unittest.TestCase): # checksum test cases @@ -461,21 +445,3 @@ if __name__ == "__main__": test_main() - -def test(tests=''): - if not tests: tests = 'o' - testcases = [] - if 'k' in tests: testcases.append(ChecksumTestCase) - if 'x' in tests: testcases.append(ExceptionTestCase) - if 'c' in tests: testcases.append(CompressTestCase) - if 'o' in tests: testcases.append(CompressObjectTestCase) - test_support.run_unittest(*testcases) - -if False: - import sys - sys.path.insert(1, '/Py23Src/python/dist/src/Lib/test') - import test_zlib as tz - ts, ut = tz.test_support, tz.unittest - su = ut.TestSuite() - su.addTest(ut.makeSuite(tz.CompressTestCase)) - ts.run_suite(su) From python-checkins at python.org Tue Apr 24 06:53:17 2007 From: python-checkins at python.org (neal.norwitz) Date: Tue, 24 Apr 2007 06:53:17 +0200 (CEST) Subject: [Python-checkins] r54932 - in python/trunk: Doc/lib/liburllib2.tex Lib/urllib2.py Message-ID: <20070424045317.5181D1E400A@bag.python.org> Author: neal.norwitz Date: Tue Apr 24 06:53:12 2007 New Revision: 54932 Modified: python/trunk/Doc/lib/liburllib2.tex python/trunk/Lib/urllib2.py Log: Fix SF #1703110, Incorrect example for add_password() (use uri, not host) Modified: python/trunk/Doc/lib/liburllib2.tex ============================================================================== --- python/trunk/Doc/lib/liburllib2.tex (original) +++ python/trunk/Doc/lib/liburllib2.tex Tue Apr 24 06:53:12 2007 @@ -817,7 +817,10 @@ import urllib2 # Create an OpenerDirector with support for Basic HTTP Authentication... auth_handler = urllib2.HTTPBasicAuthHandler() -auth_handler.add_password('realm', 'host', 'username', 'password') +auth_handler.add_password(realm='PDQ Application', + uri='https://mahler:8092/site-updates.py', + user='klem', + passwd='kadidd!ehopper') opener = urllib2.build_opener(auth_handler) # ...and install it globally so it can be used with urlopen. urllib2.install_opener(opener) Modified: python/trunk/Lib/urllib2.py ============================================================================== --- python/trunk/Lib/urllib2.py (original) +++ python/trunk/Lib/urllib2.py Tue Apr 24 06:53:12 2007 @@ -55,7 +55,10 @@ # set up authentication info authinfo = urllib2.HTTPBasicAuthHandler() -authinfo.add_password('realm', 'host', 'username', 'password') +authinfo.add_password(realm='PDQ Application', + uri='https://mahler:8092/site-updates.py', + user='klem', + passwd='geheim$parole') proxy_support = urllib2.ProxyHandler({"http" : "http://ahad-haam:3128"}) From python-checkins at python.org Tue Apr 24 06:54:28 2007 From: python-checkins at python.org (neal.norwitz) Date: Tue, 24 Apr 2007 06:54:28 +0200 (CEST) Subject: [Python-checkins] r54933 - in python/branches/release25-maint: Doc/lib/liburllib2.tex Lib/urllib2.py Message-ID: <20070424045428.CB7EE1E400A@bag.python.org> Author: neal.norwitz Date: Tue Apr 24 06:54:24 2007 New Revision: 54933 Modified: python/branches/release25-maint/Doc/lib/liburllib2.tex python/branches/release25-maint/Lib/urllib2.py Log: Fix SF #1703110, Incorrect example for add_password() (use uri, not host) Modified: python/branches/release25-maint/Doc/lib/liburllib2.tex ============================================================================== --- python/branches/release25-maint/Doc/lib/liburllib2.tex (original) +++ python/branches/release25-maint/Doc/lib/liburllib2.tex Tue Apr 24 06:54:24 2007 @@ -817,7 +817,10 @@ import urllib2 # Create an OpenerDirector with support for Basic HTTP Authentication... auth_handler = urllib2.HTTPBasicAuthHandler() -auth_handler.add_password('realm', 'host', 'username', 'password') +auth_handler.add_password(realm='PDQ Application', + uri='https://mahler:8092/site-updates.py', + user='klem', + passwd='kadidd!ehopper') opener = urllib2.build_opener(auth_handler) # ...and install it globally so it can be used with urlopen. urllib2.install_opener(opener) Modified: python/branches/release25-maint/Lib/urllib2.py ============================================================================== --- python/branches/release25-maint/Lib/urllib2.py (original) +++ python/branches/release25-maint/Lib/urllib2.py Tue Apr 24 06:54:24 2007 @@ -55,7 +55,10 @@ # set up authentication info authinfo = urllib2.HTTPBasicAuthHandler() -authinfo.add_password('realm', 'host', 'username', 'password') +authinfo.add_password(realm='PDQ Application', + uri='https://mahler:8092/site-updates.py', + user='klem', + passwd='geheim$parole') proxy_support = urllib2.ProxyHandler({"http" : "http://ahad-haam:3128"}) From buildbot at python.org Tue Apr 24 07:31:16 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Apr 2007 05:31:16 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP trunk Message-ID: <20070424053116.006D01E400A@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/389 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings failed slave lost sincerely, -The Buildbot From buildbot at python.org Tue Apr 24 07:38:59 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Apr 2007 05:38:59 +0000 Subject: [Python-checkins] buildbot failure in x86 XP trunk Message-ID: <20070424053859.575391E400A@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/390 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: neal.norwitz BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Tue Apr 24 12:36:45 2007 From: python-checkins at python.org (georg.brandl) Date: Tue, 24 Apr 2007 12:36:45 +0200 (CEST) Subject: [Python-checkins] r54934 - in python/trunk: Doc/commontex/copyright.tex Doc/commontex/license.tex Doc/lib/email.tex LICENSE Message-ID: <20070424103645.314251E400A@bag.python.org> Author: georg.brandl Date: Tue Apr 24 12:36:42 2007 New Revision: 54934 Modified: python/trunk/Doc/commontex/copyright.tex python/trunk/Doc/commontex/license.tex python/trunk/Doc/lib/email.tex python/trunk/LICENSE Log: Some new year updates. Modified: python/trunk/Doc/commontex/copyright.tex ============================================================================== --- python/trunk/Doc/commontex/copyright.tex (original) +++ python/trunk/Doc/commontex/copyright.tex Tue Apr 24 12:36:42 2007 @@ -1,4 +1,4 @@ -Copyright \copyright{} 2001-2006 Python Software Foundation. +Copyright \copyright{} 2001-2007 Python Software Foundation. All rights reserved. Copyright \copyright{} 2000 BeOpen.com. Modified: python/trunk/Doc/commontex/license.tex ============================================================================== --- python/trunk/Doc/commontex/license.tex (original) +++ python/trunk/Doc/commontex/license.tex Tue Apr 24 12:36:42 2007 @@ -52,6 +52,7 @@ \linev{2.4.3}{2.4.2}{2006}{PSF}{yes} \linev{2.4.4}{2.4.3}{2006}{PSF}{yes} \linev{2.5}{2.4}{2006}{PSF}{yes} + \linev{2.5.1}{2.5}{2007}{PSF}{yes} \end{tablev} \note{GPL-compatible doesn't mean that we're distributing @@ -82,7 +83,7 @@ prepare derivative works, distribute, and otherwise use Python \version{} alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., -``Copyright \copyright{} 2001-2006 Python Software Foundation; All +``Copyright \copyright{} 2001-2007 Python Software Foundation; All Rights Reserved'' are retained in Python \version{} alone or in any derivative version prepared by Licensee. Modified: python/trunk/Doc/lib/email.tex ============================================================================== --- python/trunk/Doc/lib/email.tex (original) +++ python/trunk/Doc/lib/email.tex Tue Apr 24 12:36:42 2007 @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2006 Python Software Foundation +% Copyright (C) 2001-2007 Python Software Foundation % Author: barry at python.org (Barry Warsaw) \section{\module{email} --- Modified: python/trunk/LICENSE ============================================================================== --- python/trunk/LICENSE (original) +++ python/trunk/LICENSE Tue Apr 24 12:36:42 2007 @@ -52,7 +52,9 @@ 2.4.1 2.4 2005 PSF yes 2.4.2 2.4.1 2005 PSF yes 2.4.3 2.4.2 2006 PSF yes + 2.4.4 2.4.3 2006 PSF yes 2.5 2.4 2006 PSF yes + 2.5.1 2.5 2007 PSF yes Footnotes: From python-checkins at python.org Tue Apr 24 12:36:48 2007 From: python-checkins at python.org (georg.brandl) Date: Tue, 24 Apr 2007 12:36:48 +0200 (CEST) Subject: [Python-checkins] r54935 - in python/branches/release25-maint: Doc/commontex/copyright.tex Doc/commontex/license.tex LICENSE Message-ID: <20070424103648.1AB6D1E400A@bag.python.org> Author: georg.brandl Date: Tue Apr 24 12:36:45 2007 New Revision: 54935 Modified: python/branches/release25-maint/Doc/commontex/copyright.tex python/branches/release25-maint/Doc/commontex/license.tex python/branches/release25-maint/LICENSE Log: Some new year updates. Modified: python/branches/release25-maint/Doc/commontex/copyright.tex ============================================================================== --- python/branches/release25-maint/Doc/commontex/copyright.tex (original) +++ python/branches/release25-maint/Doc/commontex/copyright.tex Tue Apr 24 12:36:45 2007 @@ -1,4 +1,4 @@ -Copyright \copyright{} 2001-2006 Python Software Foundation. +Copyright \copyright{} 2001-2007 Python Software Foundation. All rights reserved. Copyright \copyright{} 2000 BeOpen.com. Modified: python/branches/release25-maint/Doc/commontex/license.tex ============================================================================== --- python/branches/release25-maint/Doc/commontex/license.tex (original) +++ python/branches/release25-maint/Doc/commontex/license.tex Tue Apr 24 12:36:45 2007 @@ -50,6 +50,7 @@ \linev{2.4.1}{2.4}{2005}{PSF}{yes} \linev{2.4.2}{2.4.1}{2005}{PSF}{yes} \linev{2.4.3}{2.4.2}{2006}{PSF}{yes} + \linev{2.4.4}{2.4.3}{2006}{PSF}{yes} \linev{2.5}{2.4}{2006}{PSF}{yes} \linev{2.5.1}{2.5}{2007}{PSF}{yes} \end{tablev} @@ -82,7 +83,7 @@ prepare derivative works, distribute, and otherwise use Python \version{} alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., -``Copyright \copyright{} 2001-2006 Python Software Foundation; All +``Copyright \copyright{} 2001-2007 Python Software Foundation; All Rights Reserved'' are retained in Python \version{} alone or in any derivative version prepared by Licensee. Modified: python/branches/release25-maint/LICENSE ============================================================================== --- python/branches/release25-maint/LICENSE (original) +++ python/branches/release25-maint/LICENSE Tue Apr 24 12:36:45 2007 @@ -52,6 +52,7 @@ 2.4.1 2.4 2005 PSF yes 2.4.2 2.4.1 2005 PSF yes 2.4.3 2.4.2 2006 PSF yes + 2.4.4 2.4.3 2006 PSF yes 2.5 2.4 2006 PSF yes 2.5.1 2.5 2007 PSF yes From python-checkins at python.org Tue Apr 24 15:54:40 2007 From: python-checkins at python.org (facundo.batista) Date: Tue, 24 Apr 2007 15:54:40 +0200 (CEST) Subject: [Python-checkins] r54938 - python/trunk/Misc/NEWS Message-ID: <20070424135440.713981E400A@bag.python.org> Author: facundo.batista Date: Tue Apr 24 15:54:38 2007 New Revision: 54938 Modified: python/trunk/Misc/NEWS Log: Added a comment about last change in urllib2.py (all 2xx responses are ok now). Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Apr 24 15:54:38 2007 @@ -209,6 +209,10 @@ Library ------- +- As specified in RFC 2616, an HTTP response like 2xx indicates that + the client's request was successfully received, understood, and accepted. + Now in these cases no error is raised in urllib2. + - Bug #1290505: time.strptime's internal cache of locale information is now properly recreated when the locale is changed. From facundobatista at gmail.com Tue Apr 24 15:58:08 2007 From: facundobatista at gmail.com (Facundo Batista) Date: Tue, 24 Apr 2007 10:58:08 -0300 Subject: [Python-checkins] r54927 - in python/trunk/Lib: test/test_urllib2.py urllib2.py In-Reply-To: References: <20070423170836.5BE601E4017@bag.python.org> Message-ID: 2007/4/24, Neal Norwitz : > Can you add a note to Misc/NEWS about this? Done, sorry I forgot. > Also, should this be backported? This was a bug, and nobody raised any objection about fixing it. Changes the behaviour of the situation, but I think that this should be backported. Could you please do it or need me to do it? Regards, -- . Facundo Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org/ar/ From python-checkins at python.org Tue Apr 24 17:10:12 2007 From: python-checkins at python.org (georg.brandl) Date: Tue, 24 Apr 2007 17:10:12 +0200 (CEST) Subject: [Python-checkins] r54939 - python/trunk/Doc/lib/libsys.tex Message-ID: <20070424151012.0A2C61E400D@bag.python.org> Author: georg.brandl Date: Tue Apr 24 17:10:09 2007 New Revision: 54939 Modified: python/trunk/Doc/lib/libsys.tex Log: Bug #1705717: error in sys.argv docs. Modified: python/trunk/Doc/lib/libsys.tex ============================================================================== --- python/trunk/Doc/lib/libsys.tex (original) +++ python/trunk/Doc/lib/libsys.tex Tue Apr 24 17:10:09 2007 @@ -15,8 +15,8 @@ whether this is a full pathname or not). If the command was executed using the \programopt{-c} command line option to the interpreter, \code{argv[0]} is set to the string \code{'-c'}. If no - script name was passed to the Python interpreter, \code{argv} has - zero length. + script name was passed to the Python interpreter, \code{argv[0]} is + the empty string. \end{datadesc} \begin{datadesc}{byteorder} From python-checkins at python.org Tue Apr 24 17:10:17 2007 From: python-checkins at python.org (georg.brandl) Date: Tue, 24 Apr 2007 17:10:17 +0200 (CEST) Subject: [Python-checkins] r54940 - python/branches/release25-maint/Doc/lib/libsys.tex Message-ID: <20070424151017.6AB5A1E400B@bag.python.org> Author: georg.brandl Date: Tue Apr 24 17:10:16 2007 New Revision: 54940 Modified: python/branches/release25-maint/Doc/lib/libsys.tex Log: Bug #1705717: error in sys.argv docs. (backport from rev. 54939) Modified: python/branches/release25-maint/Doc/lib/libsys.tex ============================================================================== --- python/branches/release25-maint/Doc/lib/libsys.tex (original) +++ python/branches/release25-maint/Doc/lib/libsys.tex Tue Apr 24 17:10:16 2007 @@ -15,8 +15,8 @@ whether this is a full pathname or not). If the command was executed using the \programopt{-c} command line option to the interpreter, \code{argv[0]} is set to the string \code{'-c'}. If no - script name was passed to the Python interpreter, \code{argv} has - zero length. + script name was passed to the Python interpreter, \code{argv[0]} is + the empty string. \end{datadesc} \begin{datadesc}{byteorder} From python-checkins at python.org Tue Apr 24 17:27:19 2007 From: python-checkins at python.org (georg.brandl) Date: Tue, 24 Apr 2007 17:27:19 +0200 (CEST) Subject: [Python-checkins] r54941 - in python/trunk: Lib/distutils/command/build_ext.py Misc/NEWS Message-ID: <20070424152719.A16751E400B@bag.python.org> Author: georg.brandl Date: Tue Apr 24 17:27:13 2007 New Revision: 54941 Modified: python/trunk/Lib/distutils/command/build_ext.py python/trunk/Misc/NEWS Log: Bug #1706381: Specifying the SWIG option "-c++" in the setup.py file (as opposed to the command line) will now write file names ending in ".cpp" too. Modified: python/trunk/Lib/distutils/command/build_ext.py ============================================================================== --- python/trunk/Lib/distutils/command/build_ext.py (original) +++ python/trunk/Lib/distutils/command/build_ext.py Tue Apr 24 17:27:13 2007 @@ -533,7 +533,8 @@ if self.swig_cpp: log.warn("--swig-cpp is deprecated - use --swig-opts=-c++") - if self.swig_cpp or ('-c++' in self.swig_opts): + if self.swig_cpp or ('-c++' in self.swig_opts) or \ + ('-c++' in extension.swig_opts): target_ext = '.cpp' else: target_ext = '.c' Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Apr 24 17:27:13 2007 @@ -209,6 +209,10 @@ Library ------- +- Bug #1706381: Specifying the SWIG option "-c++" in the setup.py file + (as opposed to the command line) will now write file names ending in + ".cpp" too. + - As specified in RFC 2616, an HTTP response like 2xx indicates that the client's request was successfully received, understood, and accepted. Now in these cases no error is raised in urllib2. From python-checkins at python.org Tue Apr 24 17:27:26 2007 From: python-checkins at python.org (georg.brandl) Date: Tue, 24 Apr 2007 17:27:26 +0200 (CEST) Subject: [Python-checkins] r54942 - in python/branches/release25-maint: Lib/distutils/command/build_ext.py Misc/NEWS Message-ID: <20070424152726.B57DB1E400A@bag.python.org> Author: georg.brandl Date: Tue Apr 24 17:27:25 2007 New Revision: 54942 Modified: python/branches/release25-maint/Lib/distutils/command/build_ext.py python/branches/release25-maint/Misc/NEWS Log: Bug #1706381: Specifying the SWIG option "-c++" in the setup.py file (as opposed to the command line) will now write file names ending in ".cpp" too. (backport from rev. 54941) Modified: python/branches/release25-maint/Lib/distutils/command/build_ext.py ============================================================================== --- python/branches/release25-maint/Lib/distutils/command/build_ext.py (original) +++ python/branches/release25-maint/Lib/distutils/command/build_ext.py Tue Apr 24 17:27:25 2007 @@ -533,7 +533,8 @@ if self.swig_cpp: log.warn("--swig-cpp is deprecated - use --swig-opts=-c++") - if self.swig_cpp or ('-c++' in self.swig_opts): + if self.swig_cpp or ('-c++' in self.swig_opts) or \ + ('-c++' in extension.swig_opts): target_ext = '.cpp' else: target_ext = '.c' Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Tue Apr 24 17:27:25 2007 @@ -12,6 +12,10 @@ Library ------- +- Bug #1706381: Specifying the SWIG option "-c++" in the setup.py file + (as opposed to the command line) will now write file names ending in + ".cpp" too. + - Patch #1695229: Fix a regression with tarfile.open() and a missing name argument. From buildbot at python.org Tue Apr 24 18:46:42 2007 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Apr 2007 16:46:42 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP 2.5 Message-ID: <20070424164644.3B5561E4012@bag.python.org> The Buildbot has detected a new failure of x86 XP 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%25202.5/builds/214 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: georg.brandl Build had warnings: warnings failed slave lost sincerely, -The Buildbot From python-checkins at python.org Wed Apr 25 00:04:29 2007 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 25 Apr 2007 00:04:29 +0200 (CEST) Subject: [Python-checkins] r54943 - python/branches/release25-maint/Doc/lib/libfuncs.tex Message-ID: <20070424220429.1A7CE1E4007@bag.python.org> Author: raymond.hettinger Date: Wed Apr 25 00:04:26 2007 New Revision: 54943 Modified: python/branches/release25-maint/Doc/lib/libfuncs.tex Log: Fix markup Modified: python/branches/release25-maint/Doc/lib/libfuncs.tex ============================================================================== --- python/branches/release25-maint/Doc/lib/libfuncs.tex (original) +++ python/branches/release25-maint/Doc/lib/libfuncs.tex Wed Apr 25 00:04:26 2007 @@ -972,7 +972,7 @@ \begin{funcdesc}{reversed}{seq} Return a reverse iterator. \var{seq} must be an object which - supports the sequence protocol (the __len__() method and the + supports the sequence protocol (the \method{__len__()} method and the \method{__getitem__()} method with integer arguments starting at \code{0}). \versionadded{2.4} From python-checkins at python.org Wed Apr 25 00:13:46 2007 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 25 Apr 2007 00:13:46 +0200 (CEST) Subject: [Python-checkins] r54944 - python/trunk/Doc/lib/libfuncs.tex Message-ID: <20070424221346.E68941E4007@bag.python.org> Author: raymond.hettinger Date: Wed Apr 25 00:13:43 2007 New Revision: 54944 Modified: python/trunk/Doc/lib/libfuncs.tex Log: Fix markup Modified: python/trunk/Doc/lib/libfuncs.tex ============================================================================== --- python/trunk/Doc/lib/libfuncs.tex (original) +++ python/trunk/Doc/lib/libfuncs.tex Wed Apr 25 00:13:43 2007 @@ -996,7 +996,7 @@ \begin{funcdesc}{reversed}{seq} Return a reverse iterator. \var{seq} must be an object which - supports the sequence protocol (the __len__() method and the + supports the sequence protocol (the \method{__len__()} method and the \method{__getitem__()} method with integer arguments starting at \code{0}). \versionadded{2.4} From python-checkins at python.org Wed Apr 25 02:11:02 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Wed, 25 Apr 2007 02:11:02 +0200 (CEST) Subject: [Python-checkins] r54945 - in python/trunk: Modules/_ctypes/callproc.c Modules/cPickle.c Modules/cStringIO.c Modules/posixmodule.c PC/_winreg.c Python/thread_nt.h Message-ID: <20070425001102.7BC231E400A@bag.python.org> Author: kristjan.jonsson Date: Wed Apr 25 02:10:50 2007 New Revision: 54945 Modified: python/trunk/Modules/_ctypes/callproc.c python/trunk/Modules/cPickle.c python/trunk/Modules/cStringIO.c python/trunk/Modules/posixmodule.c python/trunk/PC/_winreg.c python/trunk/Python/thread_nt.h Log: Merge change 54909 from release25-maint: Fix several minor issues discovered using code analysis in VisualStudio 2005 Team Edition Modified: python/trunk/Modules/_ctypes/callproc.c ============================================================================== --- python/trunk/Modules/_ctypes/callproc.c (original) +++ python/trunk/Modules/_ctypes/callproc.c Wed Apr 25 02:10:50 2007 @@ -64,6 +64,7 @@ #ifdef MS_WIN32 #include +#include #else #include "ctypes_dlfcn.h" #endif @@ -97,9 +98,9 @@ 0, NULL); if (n) { - while (isspace(lpMsgBuf[n-1])) + while (_istspace(lpMsgBuf[n-1])) --n; - lpMsgBuf[n] = '\0'; /* rstrip() */ + lpMsgBuf[n] = _T('\0'); /* rstrip() */ } return lpMsgBuf; } Modified: python/trunk/Modules/cPickle.c ============================================================================== --- python/trunk/Modules/cPickle.c (original) +++ python/trunk/Modules/cPickle.c Wed Apr 25 02:10:50 2007 @@ -533,11 +533,12 @@ self->buf_size = size; } else if (n > self->buf_size) { - self->buf = (char *)realloc(self->buf, n); - if (!self->buf) { + char *newbuf = (char *)realloc(self->buf, n); + if (!newbuf) { PyErr_NoMemory(); return -1; } + self->buf = newbuf; self->buf_size = n; } @@ -576,6 +577,7 @@ i = 0; while (1) { int bigger; + char *newbuf; for (; i < (self->buf_size - 1); i++) { if (feof(self->fp) || (self->buf[i] = getc(self->fp)) == '\n') { @@ -589,11 +591,12 @@ PyErr_NoMemory(); return -1; } - self->buf = (char *)realloc(self->buf, bigger); - if (!self->buf) { + newbuf = (char *)realloc(self->buf, bigger); + if (!newbuf) { PyErr_NoMemory(); return -1; } + self->buf = newbuf; self->buf_size = bigger; } } @@ -4365,17 +4368,19 @@ */ if ((self->num_marks + 1) >= self->marks_size) { + int *marks; s=self->marks_size+20; if (s <= self->num_marks) s=self->num_marks + 1; if (self->marks == NULL) - self->marks=(int *)malloc(s * sizeof(int)); + marks=(int *)malloc(s * sizeof(int)); else - self->marks=(int *)realloc(self->marks, + marks=(int *)realloc(self->marks, s * sizeof(int)); - if (! self->marks) { + if (!marks) { PyErr_NoMemory(); return -1; } + self->marks = marks; self->marks_size = s; } Modified: python/trunk/Modules/cStringIO.c ============================================================================== --- python/trunk/Modules/cStringIO.c (original) +++ python/trunk/Modules/cStringIO.c Wed Apr 25 02:10:50 2007 @@ -349,13 +349,17 @@ } if (position > self->buf_size) { + char *newbuf; self->buf_size*=2; if (self->buf_size <= position) self->buf_size=position+1; - self->buf = (char*) realloc(self->buf,self->buf_size); - if (!self->buf) { + newbuf = (char*) realloc(self->buf,self->buf_size); + if (!newbuf) { + free(self->buf); + self->buf = 0; self->buf_size=self->pos=0; return PyErr_NoMemory(); } + self->buf = newbuf; } else if (position < 0) position=0; @@ -376,6 +380,7 @@ O_cwrite(PyObject *self, const char *c, Py_ssize_t l) { Py_ssize_t newl; Oobject *oself; + char *newbuf; if (!IO__opencheck(IOOOBJECT(self))) return -1; oself = (Oobject *)self; @@ -387,12 +392,15 @@ assert(newl + 1 < INT_MAX); oself->buf_size = (int)(newl+1); } - oself->buf = (char*)realloc(oself->buf, oself->buf_size); - if (!oself->buf) { + newbuf = (char*)realloc(oself->buf, oself->buf_size); + if (!newbuf) { PyErr_SetString(PyExc_MemoryError,"out of memory"); + free(oself->buf); + oself->buf = 0; oself->buf_size = oself->pos = 0; return -1; } + oself->buf = newbuf; } memcpy(oself->buf+oself->pos,c,l); Modified: python/trunk/Modules/posixmodule.c ============================================================================== --- python/trunk/Modules/posixmodule.c (original) +++ python/trunk/Modules/posixmodule.c Wed Apr 25 02:10:50 2007 @@ -4841,18 +4841,19 @@ (sizeof(modulepath)/sizeof(modulepath[0])) -strlen(modulepath)); if (stat(modulepath, &statinfo) != 0) { + size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]); /* Eeek - file-not-found - possibly an embedding situation - see if we can locate it in sys.prefix */ strncpy(modulepath, Py_GetExecPrefix(), - sizeof(modulepath)/sizeof(modulepath[0])); + mplen); + modulepath[mplen-1] = '\0'; if (modulepath[strlen(modulepath)-1] != '\\') strcat(modulepath, "\\"); strncat(modulepath, szConsoleSpawn, - (sizeof(modulepath)/sizeof(modulepath[0])) - -strlen(modulepath)); + mplen-strlen(modulepath)); /* No where else to look - raise an easily identifiable error, rather than leaving Windows to report "file not found" - as the user is probably blissfully Modified: python/trunk/PC/_winreg.c ============================================================================== --- python/trunk/PC/_winreg.c (original) +++ python/trunk/PC/_winreg.c Wed Apr 25 02:10:50 2007 @@ -699,7 +699,7 @@ case REG_DWORD: if (value != Py_None && !PyInt_Check(value)) return FALSE; - *retDataBuf = (BYTE *)PyMem_NEW(DWORD, sizeof(DWORD)); + *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1); if (*retDataBuf==NULL){ PyErr_NoMemory(); return FALSE; Modified: python/trunk/Python/thread_nt.h ============================================================================== --- python/trunk/Python/thread_nt.h (original) +++ python/trunk/Python/thread_nt.h Wed Apr 25 02:10:50 2007 @@ -202,12 +202,12 @@ * too many threads". */ dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n", - PyThread_get_thread_ident(), rv, errno)); + PyThread_get_thread_ident(), (void*)rv, errno)); obj.id = -1; } else { dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", - PyThread_get_thread_ident(), rv)); + PyThread_get_thread_ident(), (void*)rv)); /* wait for thread to initialize, so we can get its id */ WaitForSingleObject(obj.done, INFINITE); assert(obj.id != -1); @@ -333,7 +333,7 @@ dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); + dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError())); } /* minimum/maximum thread stack sizes supported */ From python-checkins at python.org Wed Apr 25 02:17:29 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 25 Apr 2007 02:17:29 +0200 (CEST) Subject: [Python-checkins] r54946 - peps/trunk/pep-3119.txt Message-ID: <20070425001729.D0F9F1E400A@bag.python.org> Author: guido.van.rossum Date: Wed Apr 25 02:17:23 2007 New Revision: 54946 Modified: peps/trunk/pep-3119.txt Log: Add pointer to implementation of @abstractmethod in C. Change ABC framework description to only mention @abstractmethod and unconditionally propose it as a built-in. Some more editorializing; explain why we have BasicMapping. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Wed Apr 25 02:17:23 2007 @@ -16,9 +16,9 @@ This is a proposal to add Abstract Base Class (ABC) support to Python 3000. It proposes: -* An "ABC support framework" which defines a metaclass, a base class, - a decorator, and some helpers that make it easy to define ABCs. - This will be added as a new library module named "abc". +* An "ABC support framework" which defines a built-in decorator that + can be used to define abstract methods. A class containing an + abstract method that isn't overridden cannot be instantiated. * Specific ABCs for containers and iterators, to be added to the collections module. @@ -119,10 +119,10 @@ Specification ============= -The specification follows the four categories listed in the abstract: +The specification follows the categories listed in the abstract: -* An "ABC support framework" which defines a metaclass, a base class, - a decorator, and some helpers that make it easy to define ABCs. +* An "ABC support framework" which defines a built-in decorator that + make it easy to define ABCs, and mechanisms to support it. * Specific ABCs for containers and iterators, to be added to the collections module. @@ -131,58 +131,48 @@ ABC Support Framework --------------------- -We define the following four new built-in objects that help defining -ABCs: +We define a new built-in decorator, ``@abstractmethod``, to be used to +declare abstract methods. A class containing at least one method +declared with this decorator that hasn't been overridden yet cannot be +instantiated. Such a methods may be called from the overriding method +in the subclass (using ``super`` or direct invocation). For example:: -``@abstractmethod`` - A decorator used to declare abstract methods. This should only be - used with classes whose class is derived from ``Abstract`` below. - A class containing at least one method declared with this - decorator that hasn't been overridden yet cannot be instantiated. - Such a methods may be called from the overriding method in the - subclass (using ``super`` or direct invocation). - -``AbstractClass`` - A metaclass to be used with classes containing abstract methods. - Classes whose metaclass is (or derives from) ``AbstractClass`` - cannot be instantiated unless all methods declared abstract using - the ``@abstractmethod`` decorator have been overridden by concrete - methods. - -``Abstract`` - An empty helper class whose metaclass is ``AbstractClass``. This - only exists as a minor convenience; deriving a class from - ``Abstract`` is the same as setting its metaclass to - ``AbstractClass``. - - -``AbstractInstantiationError`` - The exception raised when attempting to instantiate an abstract - class. It derives from ``TypeError``. - -**Open issues:** - -* Implementing the prohibition on instantiation may weigh down - instance creation of popular built-in classes like ``tuple`` or - ``str``. Perhaps concrete built-in classes can use a shortcut; or - perhaps there's a more efficient implementation. - -* Do we even need ``Abstract`` and ``AbstractClass``? Their - functionality can be subsumed into ``object`` and ``type``, - respectively. + class A: + @abstractmethod + def foo(self): pass -* Even if we keep them separate, ``Abstract`` is quite unnecessary - since there is hardly any difference in complexity between this:: + A() # raises TypeError - class C(metaclass=AbstractClass): - @abstractmethod - def foo(self): ... + class B(A): + pass - and this:: + B() # raises TypeError - class C(Abstract): - @abstractmethod - def foo(self): ... + class C(A): + def foo(self): print(42) + + C() # works + +**Implementation:** The ``@abstractmethod`` decorator sets the +function attribute ``__isabstractmethod__`` to the value ``True``. +The ``type.__new__`` method computes the type attribute +``__abstractmethods__`` as the set of all method names that have an +``__isabstractmethod__`` attribute whose value is true. It does this +by combining the ``__abstractmethods__` attributes of the base +classes, adding the names of all methods in the new class dict that +have a true ``__isabstractmethod__`` attribute, and removing the names +of all methods in the new class dict that don't have a true +``__isabstractmethod__`` attribute. If the resulting +``__abstractmethods__`` set is non-empty, the class is considered +abstract, and attempts to instantiate it will raise ``TypeError``. +(CPython can uses an internal flag ``Py_TPFLAGS_ABSTRACT`` to speed up +this check [6]_.) + +**Discussion:** Unlike C++ or Java, abstract methods as defined here +may have an implementation. This implementation can be called via the +``super`` mechanism from the class that overrides it. This could be +useful as an end-point for a super-call in framework using a +cooperative multiple-inheritance [7]_, [8]_. ABCs for Containers and Iterators @@ -279,7 +269,7 @@ The abstract ``__len__`` method returns 0. **Invariant:** If a class ``C`` derives from ``Sized`` as well as from ``Iterable``, the invariant ``sum(1 for x in o) == len(o)`` should hold for any - instance ``o`` of ``C``. **Open issue:** Is ``Sized`` the best + instance ``o`` of ``C``. **Open issues:** Is ``Sized`` the best name? Proposed alternatives already tentatively rejected: ``Finite`` (nobody understood it), ``Lengthy``, ``Sizeable`` (both too cute), ``Countable`` (the set of natural numbers is a @@ -438,7 +428,16 @@ Mappings '''''''' -These abstract classes represent various stages of mapping-ness. +These abstract classes represent various stages of mapping-ness. The +``Mapping`` class represents the most common read-only mapping API. +However, code *accepting* a mapping is encouraged to check for the +``BasicMapping`` ABC when iteration is not used. This allows for +certain "black-box" implementations that can look up values by key but +don't provide a convenient iteration API. A hypothetical example +would be an interface to a hierarchical filesystem, where keys are +pathnames relative to some root directory. Iterating over all +pathnames would presumably take forever, as would counting the number +of valid pathnames. The built-in type ``dict`` derives from ``MutableMapping``. @@ -488,10 +487,6 @@ **Open issues:** -* Do we need both ``BasicMapping`` and ``Mapping``? We could just - start with ``Mapping``; but I believe there's some use for a - non-iterable mapping that nevertheless behaves like a basic mapping. - * We should say more about mapping view types. @@ -545,8 +540,8 @@ **Open issues:** define the base interfaces for these so alternative implementations and subclasses know what they are in for. This may be -the subject of a new PEP or PEPs (maybe PEP 358 can be co-opted for -the ``bytes`` type). +the subject of a new PEP or PEPs (PEP 358 should be co-opted for the +``bytes`` type). ABCs for Numbers @@ -555,16 +550,15 @@ **Open issues:** Define: ``Number``, ``Complex``, ``Real``, ``Rational``, ``Integer``. Maybe also ``Cardinal`` (``Integer`` >= 0)? We probably also need ``Index``, which converts to ``Integer`` -using ``__index__``. This should probably be moved out to a separate -PEP. +using ``__index__``. This should be moved out to a separate PEP. Guidelines for Writing ABCs --------------------------- -Some suggestions: +Some suggestions for writing ABCs: -* Use ``@abstractmethod`` and the ``Abstract`` base class. +* Use the ``@abstractmethod`` decorator. * Define abstract methods that could be useful as an end point when called via a super chain. @@ -575,8 +569,6 @@ * Keep abstract classes small, one per use case instead of one per concept. -* What else? - ABCs vs. Alternatives ===================== @@ -680,6 +672,15 @@ .. [5] Charming Python: Scaling a new PEAK, by David Mertz (http://www-128.ibm.com/developerworks/library/l-cppeak2/) +.. [6] Implementation of @abstractmethod + (http://python.org/sf/1706989) + +.. [7] Unifying types and classes in Python 2.2, by GvR + (http://www.python.org/download/releases/2.2.3/descrintro/) + +.. [8] "Putting Metaclasses to Work: A New Dimension in Object-Oriented + Programming", by Ira R. Forman and Scott H. Danforth + (http://www.amazon.com/gp/product/0201433052) Copyright From python-checkins at python.org Wed Apr 25 02:17:42 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Wed, 25 Apr 2007 02:17:42 +0200 (CEST) Subject: [Python-checkins] r54947 - in python/trunk: Modules/_struct.c Python/import.c Python/pythonrun.c Message-ID: <20070425001742.748481E400A@bag.python.org> Author: kristjan.jonsson Date: Wed Apr 25 02:17:39 2007 New Revision: 54947 Modified: python/trunk/Modules/_struct.c python/trunk/Python/import.c python/trunk/Python/pythonrun.c Log: Make pythoncore compile cleanly with VisualStudio 2005. Used an explicit typecast to get a 64 bit integer, and undefined the Yield macro that conflicts with winbase.h Modified: python/trunk/Modules/_struct.c ============================================================================== --- python/trunk/Modules/_struct.c (original) +++ python/trunk/Modules/_struct.c Wed Apr 25 02:17:39 2007 @@ -849,7 +849,7 @@ } while (--i > 0); /* Extend the sign bit. */ if (SIZEOF_LONG_LONG > f->size) - x |= -(x & (1L << ((8 * f->size) - 1))); + x |= -(x & ((PY_LONG_LONG)1 << ((8 * f->size) - 1))); if (x >= LONG_MIN && x <= LONG_MAX) return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); return PyLong_FromLongLong(x); @@ -1085,7 +1085,7 @@ } while (i > 0); /* Extend the sign bit. */ if (SIZEOF_LONG_LONG > f->size) - x |= -(x & (1L << ((8 * f->size) - 1))); + x |= -(x & ((PY_LONG_LONG)1 << ((8 * f->size) - 1))); if (x >= LONG_MIN && x <= LONG_MAX) return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); return PyLong_FromLongLong(x); Modified: python/trunk/Python/import.c ============================================================================== --- python/trunk/Python/import.c (original) +++ python/trunk/Python/import.c Wed Apr 25 02:17:39 2007 @@ -4,6 +4,7 @@ #include "Python.h" #include "Python-ast.h" +#undef Yield /* undefine macro conflicting with winbase.h */ #include "pyarena.h" #include "pythonrun.h" #include "errcode.h" Modified: python/trunk/Python/pythonrun.c ============================================================================== --- python/trunk/Python/pythonrun.c (original) +++ python/trunk/Python/pythonrun.c Wed Apr 25 02:17:39 2007 @@ -4,6 +4,7 @@ #include "Python.h" #include "Python-ast.h" +#undef Yield /* undefine macro conflicting with winbase.h */ #include "grammar.h" #include "node.h" #include "token.h" From python-checkins at python.org Wed Apr 25 02:19:30 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Wed, 25 Apr 2007 02:19:30 +0200 (CEST) Subject: [Python-checkins] r54948 - python/trunk/Python/dynload_win.c Message-ID: <20070425001930.982CB1E400A@bag.python.org> Author: kristjan.jonsson Date: Wed Apr 25 02:19:26 2007 New Revision: 54948 Modified: python/trunk/Python/dynload_win.c Log: Remove obsolete comment. Importing of .dll files has been discontinued, only .pyd files supported on windows now. Modified: python/trunk/Python/dynload_win.c ============================================================================== --- python/trunk/Python/dynload_win.c (original) +++ python/trunk/Python/dynload_win.c Wed Apr 25 02:19:26 2007 @@ -13,16 +13,8 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef _DEBUG {"_d.pyd", "rb", C_EXTENSION}, - /* Temporarily disable .dll, to avoid conflicts between sqlite3.dll - and the sqlite3 package. If this needs to be reverted for 2.5, - some other solution for the naming conflict must be found. - {"_d.dll", "rb", C_EXTENSION}, - */ #else {".pyd", "rb", C_EXTENSION}, - /* Likewise - {".dll", "rb", C_EXTENSION}, - */ #endif {0, 0} }; From buildbot at python.org Wed Apr 25 02:52:37 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 00:52:37 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP trunk Message-ID: <20070425005237.E496C1E400A@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/393 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: kristjan.jonsson,raymond.hettinger Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_profile sincerely, -The Buildbot From buildbot at python.org Wed Apr 25 03:04:13 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 01:04:13 +0000 Subject: [Python-checkins] buildbot warnings in ia64 Ubuntu trunk trunk Message-ID: <20070425010413.CE6F41E400A@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%2520Ubuntu%2520trunk%2520trunk/builds/601 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: kristjan.jonsson,raymond.hettinger Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_ctypes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Apr 25 08:25:03 2007 From: python-checkins at python.org (georg.brandl) Date: Wed, 25 Apr 2007 08:25:03 +0200 (CEST) Subject: [Python-checkins] r54949 - in python/trunk: Doc/mac/using.tex Misc/NEWS Message-ID: <20070425062503.7098B1E400B@bag.python.org> Author: georg.brandl Date: Wed Apr 25 08:24:59 2007 New Revision: 54949 Modified: python/trunk/Doc/mac/using.tex python/trunk/Misc/NEWS Log: Patch #1698768: updated the "using Python on the Mac" intro. Modified: python/trunk/Doc/mac/using.tex ============================================================================== --- python/trunk/Doc/mac/using.tex (original) +++ python/trunk/Doc/mac/using.tex Wed Apr 25 08:24:59 2007 @@ -13,206 +13,166 @@ \section{Getting and Installing MacPython \label{getting-OSX}} -Mac OS X 10.3 comes with Python 2.3 pre-installed by Apple. -This installation does not come with the IDE and other additions, however, -so to get these you need to install the \program{MacPython for Panther additions} -from the MacPython website, \url{http://www.cwi.nl/\textasciitilde jack/macpython}. - -For MacPython 2.4, or for any MacPython on earlier releases of Mac OS X, -you need to install a full distribution from the same website. +Mac OS X 10.4 comes with Python 2.3 pre-installed by Apple. However, you are +encouraged to install the most recent version of Python from the Python website +(\url{http://www.python.org}). A ``universal binary'' build of Python 2.5, which +runs natively on the Mac's new Intel and legacy PPC CPU's, is available there. What you get after installing is a number of things: \begin{itemize} - \item A \file{MacPython-2.3} folder in your \file{Applications} - folder. In here you find the PythonIDE Integrated Development Environment; - PythonLauncher, which handles double-clicking Python scripts from - the Finder; and the Package Manager. - - \item A fairly standard \UNIX{} commandline Python interpreter in - \file{/usr/local/bin/python}, but without the usual - \file{/usr/local/lib/python}. - - \item A framework \file{/Library/Frameworks/Python.framework}, where - all the action really is, but which you usually do not have to be aware of. +\item A \file{MacPython 2.5} folder in your \file{Applications} folder. In here + you find IDLE, the development environment that is a standard part of official + Python distributions; PythonLauncher, which handles double-clicking Python + scripts from the Finder; and the ``Build Applet'' tool, which allows you to + package Python scripts as standalone applications on your system. + +\item A framework \file{/Library/Frameworks/Python.framework}, which includes + the Python executable and libraries. The installer adds this location to your + shell path. To uninstall MacPython, you can simply remove these three + things. A symlink to the Python executable is placed in /usr/local/bin/. \end{itemize} -To uninstall MacPython you can simply remove these three things. +The Apple-provided build of Python is installed in +\file{/System/Library/Frameworks/Python.framework} and \file{/usr/bin/python}, +respectively. You should never modify or delete these, as they are +Apple-controlled and are used by Apple- or third-party software. + +IDLE includes a help menu that allows you to access Python documentation. If you +are completely new to Python you should start reading the tutorial introduction +in that document. -If you use the ``additions'' installer to install on top of an existing -Apple-Python you will not get the framework and the commandline interpreter, -as they have been installed by Apple already, in -\file{/System/Library/Frameworks/Python.framework} and -\file{/usr/bin/python}, respectively. You should in principle never modify -or delete these, as they are Apple-controlled and may be used by Apple- or -third-party software. - -PythonIDE contains an Apple Help Viewer book called "MacPython Help" -which you can access through its help menu. If you are completely new to -Python you should start reading the IDE introduction in that document. +If you are familiar with Python on other \UNIX{} platforms you should read the +section on running Python scripts from the \UNIX{} shell. -If you are familiar with Python on other \UNIX{} platforms you should -read the section on running Python scripts from the \UNIX{} shell. \subsection{How to run a Python script} -Your best way to get started with Python on Mac OS X is through the PythonIDE -integrated development environment, see section \ref{IDE} and use the Help -menu when the IDE is running. - -If you want to run Python scripts from the Terminal window command line -or from the Finder you first need an editor to create your script. -Mac OS X comes with a number of standard \UNIX{} command line editors, -\program{vim} and \program{emacs} among them. If you want a more Mac-like -editor \program{BBEdit} or \program{TextWrangler} from Bare Bones Software -(see \url{http://www.barebones.com/products/bbedit/index.shtml}) are -good choices. \program{AppleWorks} or any other -word processor that can save files in ASCII is also a possibility, including -\program{TextEdit} which is included with OS X. +Your best way to get started with Python on Mac OS X is through the IDLE +integrated development environment, see section \ref{IDE} and use the Help menu +when the IDE is running. + +If you want to run Python scripts from the Terminal window command line or from +the Finder you first need an editor to create your script. Mac OS X comes with a +number of standard \UNIX{} command line editors, \program{vim} and +\program{emacs} among them. If you want a more Mac-like editor, \program{BBEdit} +or \program{TextWrangler} from Bare Bones Software (see +\url{http://www.barebones.com/products/bbedit/index.shtml}) are good choices, as +is \program{TextMate} (see \url{http://macromates.com/}). Other editors include +\program{Gvim} (\url{http://macvim.org}) and \program{Aquamacs} +(\url{http://aquamacs.org}). To run your script from the Terminal window you must make sure that -\file{/usr/local/bin} is in your shell search path. +\file{/usr/local/bin} is in your shell search path. To run your script from the Finder you have two options: + \begin{itemize} - \item Drag it to \program{PythonLauncher} - \item Select \program{PythonLauncher} as the default application - to open your script (or any .py script) through the finder Info window - and double-click it. +\item Drag it to \program{PythonLauncher} +\item Select \program{PythonLauncher} as the default application to open your + script (or any .py script) through the finder Info window and double-click it. + \program{PythonLauncher} has various preferences to control how your script is + launched. Option-dragging allows you to change these for one invocation, or + use its Preferences menu to change things globally. \end{itemize} -PythonLauncher has various preferences to control how your script is launched. -Option-dragging allows you to change these for one invocation, or use its -Preferences menu to change things globally. \subsection{Running scripts with a GUI \label{osx-gui-scripts}} -There is one Mac OS X quirk that you need to be aware of: programs -that talk to the Aqua window manager (in other words, anything that has a GUI) -need to be run in a special way. Use \program{pythonw} instead of \program{python} -to start such scripts. - -\subsection{configuration} - -MacPython honours all standard \UNIX{} environment variables such as -\envvar{PYTHONPATH}, but setting these variables for programs started -from the Finder is non-standard -as the Finder does not read your \file{.profile} or \file{.cshrc} at startup. -You need to create a file \file{\textasciitilde /.MacOSX/environment.plist}. -See Apple's Technical Document QA1067 for details. +With older versions of Python, there is one Mac OS X quirk that you need to be +aware of: programs that talk to the Aqua window manager (in other words, +anything that has a GUI) need to be run in a special way. Use \program{pythonw} +instead of \program{python} to start such scripts. + +With Python 2.5, you can use either \program{python} or \program{pythonw}. + +\subsection{Configuration} + +Python on OS X honors all standard \UNIX{} environment variables such as +\envvar{PYTHONPATH}, but setting these variables for programs started from the +Finder is non-standard as the Finder does not read your \file{.profile} or +\file{.cshrc} at startup. You need to create a file \file{\textasciitilde + /.MacOSX/environment.plist}. See Apple's Technical Document QA1067 for +details. -Installing additional Python packages is most easily done through the -Package Manager, see the MacPython Help Book for details. +For more information on installation Python packages in MacPython, see section +\ref{mac-package-manager}, ``Installing Additional Python Packages.'' \section{The IDE\label{IDE}} -The \program{Python IDE} (Integrated Development Environment) is a -separate application that acts as a text editor for your Python code, -a class browser, a graphical debugger, and more. - -The online Python Help contains a quick walkthrough of the IDE that -shows the major features and how to use them. - -\subsection{Using the ``Python Interactive'' window} - -Use this window like you would use a normal \UNIX{} command line -interpreter. - -\subsection{Writing a Python Script \label{IDEwrite}} - -In addition to using the \program{Python IDE} interactively, you can -also type out a complete Python program, saving it incrementally, and -execute it or smaller selections of it. - -You can create a new script, open a previously saved script, and save -your currently open script by selecting the appropriate item in the -``File'' menu. Dropping a Python script onto the -\program{Python IDE} will open it for editing. - -When the \program{Python IDE} saves a script, it uses the creator code -settings which are available by clicking on the small black triangle -on the top right of the document window, and selecting ``save -options''. The default is to save the file with the \program{Python -IDE} as the creator, this means that you can open the file for editing -by simply double-clicking on its icon. You might want to change this -behaviour so that it will be opened by the -\program{PythonLauncher}, and run. To do this simply choose -``PythonLauncher'' from the ``save options''. Note that these -options are associated with the \emph{file} not the application. - - -\subsection{Executing a script from within the IDE - \label{IDEexecution}} - -You can run the script in the frontmost window of the \program{Python -IDE} by hitting the run all button. You should be aware, however that -if you use the Python convention \samp{if __name__ == "__main__":} the -script will \emph{not} be ``__main__'' by default. To get that -behaviour you must select the ``Run as __main__'' option from the -small black triangle on the top right of the document window. Note -that this option is associated with the \emph{file} not the -application. It \emph{will} stay active after a save, however; to shut -this feature off simply select it again. - - -\subsection{``Save as'' versus ``Save as Applet'' - \label{IDEapplet}} - -When you are done writing your Python script you have the option of -saving it as an ``applet'' (by selecting ``Save as applet'' from the -``File'' menu). This has a significant advantage in that you can drop -files or folders onto it, to pass them to the applet the way -command-line users would type them onto the command-line to pass them -as arguments to the script. However, you should make sure to save the -applet as a separate file, do not overwrite the script you are -writing, because you will not be able to edit it again. - -Accessing the items passed to the applet via ``drag-and-drop'' is done -using the standard \member{sys.argv} mechanism. See the general -documentation for more -% need to link to the appropriate place in non-Mac docs - -Note that saving a script as an applet will not make it runnable on a -system without a Python installation. - -%\subsection{Debugger} -% **NEED INFO HERE** - -%\subsection{Module Browser} -% **NEED INFO HERE** - -%\subsection{Profiler} -% **NEED INFO HERE** -% end IDE - -%\subsection{The ``Scripts'' menu} -% **NEED INFO HERE** - -\section{The Package Manager} - -Historically MacPython came with a number of useful extension packages -included, because most Macintosh users do not have access to a development -environment and C compiler. For Mac OS X that bundling is no longer done, -but a new mechanism has been made available to allow easy access to -extension packages. - -The Python Package Manager helps you installing additional packages -that enhance Python. It determines the exact MacOS version and Python -version you have and uses that information to download a database that -has packages that are tested and tried on that combination. In other -words: if something is in your Package Manager window but does not work -you are free to blame the database maintainer. - -PackageManager then checks which of the packages you have installed and -which ones are not. This should also work when you have installed packages -outside of PackageManager. You can select packages and install them, -and PackageManager will work out the requirements and install these too. - -Often PackageManager will list a package in two flavors: binary and -source. Binary should always work, source will only work if you have -installed the Apple Developer Tools. PackageManager will warn you about -this, and also about other external dependencies. +MacPython ships with the standard IDLE development environment. A good +introduction to using IDLE can be found at +\url{http://hkn.eecs.berkeley.edu/~dyoo/python/idle_intro/index.html}. + + +\section{Installing Additional Python Packages \label{mac-package-manager}} + +There are several methods to install additional Python packages: + +\begin{itemize} +\item \url{http://pythonmac.org/packages/} contains selected compiled packages + for Python 2.5, 2.4, and 2.3. +\item Packages can be installed via the standard Python distutils mode + (\samp{python setup.py install}). +\item Many packages can also be installed via the \program{setuptools} + extension. +\end{itemize} + + +\section{GUI Programming on the Mac} + +There are several options for building GUI applications on the Mac with Python. + +\emph{PyObjC} is a Python binding to Apple's Objective-C/Cocoa framework, which +is the foundation of most modern Mac development. Information on PyObjC is +available from \url{http://pybojc.sourceforge.net}. + +The standard Python GUI toolkit is \module{Tkinter}, based on the cross-platform +Tk toolkit (\url{http://www.tcl.tk}). An Aqua-native version of Tk is bundled +with OS X by Apple, and the latest version can be downloaded and installed from +\url{http://www.activestate.com}; it can also be built from source. + +\emph{wxPython} is another popular cross-platform GUI toolkit that runs natively +on Mac OS X. Packages and documentation are available from +\url{http://www.wxpython.org}. + +\emph{PyQt} is another popular cross-platform GUI toolkit that runs natively on +Mac OS X. More information can be found at +\url{http://www.riverbankcomputing.co.uk/pyqt/}. + + +\section{Distributing Python Applications on the Mac} + +The ``Build Applet'' tool that is placed in the MacPython 2.5 folder is fine for +packaging small Python scripts on your own machine to run as a standard Mac +application. This tool, however, is not robust enough to distribute Python +applications to other users. + +The standard tool for deploying standalone Python applications on the Mac is +\program{py2app}. More information on installing and using py2app can be found +at \url{http://undefined.org/python/#py2app}. + +\section{Application Scripting} + +Python can also be used to script other Mac applications via Apple's Open +Scripting Architecture (OSA); see +\url{http://appscript.sourceforge.net}. Appscript is a high-level, user-friendly +Apple event bridge that allows you to control scriptable Mac OS X applications +using ordinary Python scripts. Appscript makes Python a serious alternative to +Apple's own \emph{AppleScript} language for automating your Mac. A related +package, \emph{PyOSA}, is an OSA language component for the Python scripting +language, allowing Python code to be executed by any OSA-enabled application +(Script Editor, Mail, iTunes, etc.). PyOSA makes Python a full peer to +AppleScript. + +\section{Other Resources} + +The MacPython mailing list is an excellent support resource for Python users and +developers on the Mac: + +\url{http://www.python.org/community/sigs/current/pythonmac-sig/} + +Another useful resource is the MacPython wiki: -PackageManager is available as a separate application and also as a -function of the IDE, through the File->Package Manager menu entry. +\url{http://wiki.python.org/moin/MacPython} Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Apr 25 08:24:59 2007 @@ -755,6 +755,8 @@ Documentation ------------- +- Patch #1698768: updated the "using Python on the Mac" intro. + - Bug #1569057: Document that calling file.next() when the file is open for writing is undefined. From python-checkins at python.org Wed Apr 25 08:25:11 2007 From: python-checkins at python.org (georg.brandl) Date: Wed, 25 Apr 2007 08:25:11 +0200 (CEST) Subject: [Python-checkins] r54950 - in python/branches/release25-maint: Doc/mac/using.tex Misc/NEWS Message-ID: <20070425062511.E0F271E4013@bag.python.org> Author: georg.brandl Date: Wed Apr 25 08:25:07 2007 New Revision: 54950 Modified: python/branches/release25-maint/Doc/mac/using.tex python/branches/release25-maint/Misc/NEWS Log: Patch #1698768: updated the "using Python on the Mac" intro. (backport from rev. 54949) Modified: python/branches/release25-maint/Doc/mac/using.tex ============================================================================== --- python/branches/release25-maint/Doc/mac/using.tex (original) +++ python/branches/release25-maint/Doc/mac/using.tex Wed Apr 25 08:25:07 2007 @@ -13,206 +13,166 @@ \section{Getting and Installing MacPython \label{getting-OSX}} -Mac OS X 10.3 comes with Python 2.3 pre-installed by Apple. -This installation does not come with the IDE and other additions, however, -so to get these you need to install the \program{MacPython for Panther additions} -from the MacPython website, \url{http://www.cwi.nl/\textasciitilde jack/macpython}. - -For MacPython 2.4, or for any MacPython on earlier releases of Mac OS X, -you need to install a full distribution from the same website. +Mac OS X 10.4 comes with Python 2.3 pre-installed by Apple. However, you are +encouraged to install the most recent version of Python from the Python website +(\url{http://www.python.org}). A ``universal binary'' build of Python 2.5, which +runs natively on the Mac's new Intel and legacy PPC CPU's, is available there. What you get after installing is a number of things: \begin{itemize} - \item A \file{MacPython-2.3} folder in your \file{Applications} - folder. In here you find the PythonIDE Integrated Development Environment; - PythonLauncher, which handles double-clicking Python scripts from - the Finder; and the Package Manager. - - \item A fairly standard \UNIX{} commandline Python interpreter in - \file{/usr/local/bin/python}, but without the usual - \file{/usr/local/lib/python}. - - \item A framework \file{/Library/Frameworks/Python.framework}, where - all the action really is, but which you usually do not have to be aware of. +\item A \file{MacPython 2.5} folder in your \file{Applications} folder. In here + you find IDLE, the development environment that is a standard part of official + Python distributions; PythonLauncher, which handles double-clicking Python + scripts from the Finder; and the ``Build Applet'' tool, which allows you to + package Python scripts as standalone applications on your system. + +\item A framework \file{/Library/Frameworks/Python.framework}, which includes + the Python executable and libraries. The installer adds this location to your + shell path. To uninstall MacPython, you can simply remove these three + things. A symlink to the Python executable is placed in /usr/local/bin/. \end{itemize} -To uninstall MacPython you can simply remove these three things. +The Apple-provided build of Python is installed in +\file{/System/Library/Frameworks/Python.framework} and \file{/usr/bin/python}, +respectively. You should never modify or delete these, as they are +Apple-controlled and are used by Apple- or third-party software. + +IDLE includes a help menu that allows you to access Python documentation. If you +are completely new to Python you should start reading the tutorial introduction +in that document. -If you use the ``additions'' installer to install on top of an existing -Apple-Python you will not get the framework and the commandline interpreter, -as they have been installed by Apple already, in -\file{/System/Library/Frameworks/Python.framework} and -\file{/usr/bin/python}, respectively. You should in principle never modify -or delete these, as they are Apple-controlled and may be used by Apple- or -third-party software. - -PythonIDE contains an Apple Help Viewer book called "MacPython Help" -which you can access through its help menu. If you are completely new to -Python you should start reading the IDE introduction in that document. +If you are familiar with Python on other \UNIX{} platforms you should read the +section on running Python scripts from the \UNIX{} shell. -If you are familiar with Python on other \UNIX{} platforms you should -read the section on running Python scripts from the \UNIX{} shell. \subsection{How to run a Python script} -Your best way to get started with Python on Mac OS X is through the PythonIDE -integrated development environment, see section \ref{IDE} and use the Help -menu when the IDE is running. - -If you want to run Python scripts from the Terminal window command line -or from the Finder you first need an editor to create your script. -Mac OS X comes with a number of standard \UNIX{} command line editors, -\program{vim} and \program{emacs} among them. If you want a more Mac-like -editor \program{BBEdit} or \program{TextWrangler} from Bare Bones Software -(see \url{http://www.barebones.com/products/bbedit/index.shtml}) are -good choices. \program{AppleWorks} or any other -word processor that can save files in ASCII is also a possibility, including -\program{TextEdit} which is included with OS X. +Your best way to get started with Python on Mac OS X is through the IDLE +integrated development environment, see section \ref{IDE} and use the Help menu +when the IDE is running. + +If you want to run Python scripts from the Terminal window command line or from +the Finder you first need an editor to create your script. Mac OS X comes with a +number of standard \UNIX{} command line editors, \program{vim} and +\program{emacs} among them. If you want a more Mac-like editor, \program{BBEdit} +or \program{TextWrangler} from Bare Bones Software (see +\url{http://www.barebones.com/products/bbedit/index.shtml}) are good choices, as +is \program{TextMate} (see \url{http://macromates.com/}). Other editors include +\program{Gvim} (\url{http://macvim.org}) and \program{Aquamacs} +(\url{http://aquamacs.org}). To run your script from the Terminal window you must make sure that -\file{/usr/local/bin} is in your shell search path. +\file{/usr/local/bin} is in your shell search path. To run your script from the Finder you have two options: + \begin{itemize} - \item Drag it to \program{PythonLauncher} - \item Select \program{PythonLauncher} as the default application - to open your script (or any .py script) through the finder Info window - and double-click it. +\item Drag it to \program{PythonLauncher} +\item Select \program{PythonLauncher} as the default application to open your + script (or any .py script) through the finder Info window and double-click it. + \program{PythonLauncher} has various preferences to control how your script is + launched. Option-dragging allows you to change these for one invocation, or + use its Preferences menu to change things globally. \end{itemize} -PythonLauncher has various preferences to control how your script is launched. -Option-dragging allows you to change these for one invocation, or use its -Preferences menu to change things globally. \subsection{Running scripts with a GUI \label{osx-gui-scripts}} -There is one Mac OS X quirk that you need to be aware of: programs -that talk to the Aqua window manager (in other words, anything that has a GUI) -need to be run in a special way. Use \program{pythonw} instead of \program{python} -to start such scripts. - -\subsection{configuration} - -MacPython honours all standard \UNIX{} environment variables such as -\envvar{PYTHONPATH}, but setting these variables for programs started -from the Finder is non-standard -as the Finder does not read your \file{.profile} or \file{.cshrc} at startup. -You need to create a file \file{\textasciitilde /.MacOSX/environment.plist}. -See Apple's Technical Document QA1067 for details. +With older versions of Python, there is one Mac OS X quirk that you need to be +aware of: programs that talk to the Aqua window manager (in other words, +anything that has a GUI) need to be run in a special way. Use \program{pythonw} +instead of \program{python} to start such scripts. + +With Python 2.5, you can use either \program{python} or \program{pythonw}. + +\subsection{Configuration} + +Python on OS X honors all standard \UNIX{} environment variables such as +\envvar{PYTHONPATH}, but setting these variables for programs started from the +Finder is non-standard as the Finder does not read your \file{.profile} or +\file{.cshrc} at startup. You need to create a file \file{\textasciitilde + /.MacOSX/environment.plist}. See Apple's Technical Document QA1067 for +details. -Installing additional Python packages is most easily done through the -Package Manager, see the MacPython Help Book for details. +For more information on installation Python packages in MacPython, see section +\ref{mac-package-manager}, ``Installing Additional Python Packages.'' \section{The IDE\label{IDE}} -The \program{Python IDE} (Integrated Development Environment) is a -separate application that acts as a text editor for your Python code, -a class browser, a graphical debugger, and more. - -The online Python Help contains a quick walkthrough of the IDE that -shows the major features and how to use them. - -\subsection{Using the ``Python Interactive'' window} - -Use this window like you would use a normal \UNIX{} command line -interpreter. - -\subsection{Writing a Python Script \label{IDEwrite}} - -In addition to using the \program{Python IDE} interactively, you can -also type out a complete Python program, saving it incrementally, and -execute it or smaller selections of it. - -You can create a new script, open a previously saved script, and save -your currently open script by selecting the appropriate item in the -``File'' menu. Dropping a Python script onto the -\program{Python IDE} will open it for editing. - -When the \program{Python IDE} saves a script, it uses the creator code -settings which are available by clicking on the small black triangle -on the top right of the document window, and selecting ``save -options''. The default is to save the file with the \program{Python -IDE} as the creator, this means that you can open the file for editing -by simply double-clicking on its icon. You might want to change this -behaviour so that it will be opened by the -\program{PythonLauncher}, and run. To do this simply choose -``PythonLauncher'' from the ``save options''. Note that these -options are associated with the \emph{file} not the application. - - -\subsection{Executing a script from within the IDE - \label{IDEexecution}} - -You can run the script in the frontmost window of the \program{Python -IDE} by hitting the run all button. You should be aware, however that -if you use the Python convention \samp{if __name__ == "__main__":} the -script will \emph{not} be ``__main__'' by default. To get that -behaviour you must select the ``Run as __main__'' option from the -small black triangle on the top right of the document window. Note -that this option is associated with the \emph{file} not the -application. It \emph{will} stay active after a save, however; to shut -this feature off simply select it again. - - -\subsection{``Save as'' versus ``Save as Applet'' - \label{IDEapplet}} - -When you are done writing your Python script you have the option of -saving it as an ``applet'' (by selecting ``Save as applet'' from the -``File'' menu). This has a significant advantage in that you can drop -files or folders onto it, to pass them to the applet the way -command-line users would type them onto the command-line to pass them -as arguments to the script. However, you should make sure to save the -applet as a separate file, do not overwrite the script you are -writing, because you will not be able to edit it again. - -Accessing the items passed to the applet via ``drag-and-drop'' is done -using the standard \member{sys.argv} mechanism. See the general -documentation for more -% need to link to the appropriate place in non-Mac docs - -Note that saving a script as an applet will not make it runnable on a -system without a Python installation. - -%\subsection{Debugger} -% **NEED INFO HERE** - -%\subsection{Module Browser} -% **NEED INFO HERE** - -%\subsection{Profiler} -% **NEED INFO HERE** -% end IDE - -%\subsection{The ``Scripts'' menu} -% **NEED INFO HERE** - -\section{The Package Manager} - -Historically MacPython came with a number of useful extension packages -included, because most Macintosh users do not have access to a development -environment and C compiler. For Mac OS X that bundling is no longer done, -but a new mechanism has been made available to allow easy access to -extension packages. - -The Python Package Manager helps you installing additional packages -that enhance Python. It determines the exact MacOS version and Python -version you have and uses that information to download a database that -has packages that are tested and tried on that combination. In other -words: if something is in your Package Manager window but does not work -you are free to blame the database maintainer. - -PackageManager then checks which of the packages you have installed and -which ones are not. This should also work when you have installed packages -outside of PackageManager. You can select packages and install them, -and PackageManager will work out the requirements and install these too. - -Often PackageManager will list a package in two flavors: binary and -source. Binary should always work, source will only work if you have -installed the Apple Developer Tools. PackageManager will warn you about -this, and also about other external dependencies. +MacPython ships with the standard IDLE development environment. A good +introduction to using IDLE can be found at +\url{http://hkn.eecs.berkeley.edu/~dyoo/python/idle_intro/index.html}. + + +\section{Installing Additional Python Packages \label{mac-package-manager}} + +There are several methods to install additional Python packages: + +\begin{itemize} +\item \url{http://pythonmac.org/packages/} contains selected compiled packages + for Python 2.5, 2.4, and 2.3. +\item Packages can be installed via the standard Python distutils mode + (\samp{python setup.py install}). +\item Many packages can also be installed via the \program{setuptools} + extension. +\end{itemize} + + +\section{GUI Programming on the Mac} + +There are several options for building GUI applications on the Mac with Python. + +\emph{PyObjC} is a Python binding to Apple's Objective-C/Cocoa framework, which +is the foundation of most modern Mac development. Information on PyObjC is +available from \url{http://pybojc.sourceforge.net}. + +The standard Python GUI toolkit is \module{Tkinter}, based on the cross-platform +Tk toolkit (\url{http://www.tcl.tk}). An Aqua-native version of Tk is bundled +with OS X by Apple, and the latest version can be downloaded and installed from +\url{http://www.activestate.com}; it can also be built from source. + +\emph{wxPython} is another popular cross-platform GUI toolkit that runs natively +on Mac OS X. Packages and documentation are available from +\url{http://www.wxpython.org}. + +\emph{PyQt} is another popular cross-platform GUI toolkit that runs natively on +Mac OS X. More information can be found at +\url{http://www.riverbankcomputing.co.uk/pyqt/}. + + +\section{Distributing Python Applications on the Mac} + +The ``Build Applet'' tool that is placed in the MacPython 2.5 folder is fine for +packaging small Python scripts on your own machine to run as a standard Mac +application. This tool, however, is not robust enough to distribute Python +applications to other users. + +The standard tool for deploying standalone Python applications on the Mac is +\program{py2app}. More information on installing and using py2app can be found +at \url{http://undefined.org/python/#py2app}. + +\section{Application Scripting} + +Python can also be used to script other Mac applications via Apple's Open +Scripting Architecture (OSA); see +\url{http://appscript.sourceforge.net}. Appscript is a high-level, user-friendly +Apple event bridge that allows you to control scriptable Mac OS X applications +using ordinary Python scripts. Appscript makes Python a serious alternative to +Apple's own \emph{AppleScript} language for automating your Mac. A related +package, \emph{PyOSA}, is an OSA language component for the Python scripting +language, allowing Python code to be executed by any OSA-enabled application +(Script Editor, Mail, iTunes, etc.). PyOSA makes Python a full peer to +AppleScript. + +\section{Other Resources} + +The MacPython mailing list is an excellent support resource for Python users and +developers on the Mac: + +\url{http://www.python.org/community/sigs/current/pythonmac-sig/} + +Another useful resource is the MacPython wiki: -PackageManager is available as a separate application and also as a -function of the IDE, through the File->Package Manager menu entry. +\url{http://wiki.python.org/moin/MacPython} Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Wed Apr 25 08:25:07 2007 @@ -504,6 +504,8 @@ Documentation ------------- +- Patch #1698768: updated the "using Python on the Mac" intro. + - Patch #1489771: the syntax rules in Python Reference Manual were updated to reflect the current Python syntax. From python-checkins at python.org Wed Apr 25 08:25:55 2007 From: python-checkins at python.org (georg.brandl) Date: Wed, 25 Apr 2007 08:25:55 +0200 (CEST) Subject: [Python-checkins] r54951 - python/trunk/Doc/mac/using.tex Message-ID: <20070425062555.D7E091E4013@bag.python.org> Author: georg.brandl Date: Wed Apr 25 08:25:55 2007 New Revision: 54951 Modified: python/trunk/Doc/mac/using.tex Log: Markup fix. Modified: python/trunk/Doc/mac/using.tex ============================================================================== --- python/trunk/Doc/mac/using.tex (original) +++ python/trunk/Doc/mac/using.tex Wed Apr 25 08:25:55 2007 @@ -151,7 +151,7 @@ The standard tool for deploying standalone Python applications on the Mac is \program{py2app}. More information on installing and using py2app can be found -at \url{http://undefined.org/python/#py2app}. +at \url{http://undefined.org/python/\#py2app}. \section{Application Scripting} From python-checkins at python.org Wed Apr 25 08:25:57 2007 From: python-checkins at python.org (georg.brandl) Date: Wed, 25 Apr 2007 08:25:57 +0200 (CEST) Subject: [Python-checkins] r54952 - python/branches/release25-maint/Doc/mac/using.tex Message-ID: <20070425062557.F3FBE1E4017@bag.python.org> Author: georg.brandl Date: Wed Apr 25 08:25:57 2007 New Revision: 54952 Modified: python/branches/release25-maint/Doc/mac/using.tex Log: Markup fix. (backport from rev. 54951) Modified: python/branches/release25-maint/Doc/mac/using.tex ============================================================================== --- python/branches/release25-maint/Doc/mac/using.tex (original) +++ python/branches/release25-maint/Doc/mac/using.tex Wed Apr 25 08:25:57 2007 @@ -151,7 +151,7 @@ The standard tool for deploying standalone Python applications on the Mac is \program{py2app}. More information on installing and using py2app can be found -at \url{http://undefined.org/python/#py2app}. +at \url{http://undefined.org/python/\#py2app}. \section{Application Scripting} From python-checkins at python.org Wed Apr 25 08:30:18 2007 From: python-checkins at python.org (neal.norwitz) Date: Wed, 25 Apr 2007 08:30:18 +0200 (CEST) Subject: [Python-checkins] r54953 - in python/trunk/Lib: ctypes/__init__.py ctypes/test/test_numbers.py decimal.py ftplib.py pdb.py posixpath.py socket.py tempfile.py test/outstanding_bugs.py test/string_tests.py test/test_descr.py test/test_fileinput.py test/test_ftplib.py test/test_gc.py test/test_getopt.py test/test_httplib.py test/test_long_future.py test/test_minidom.py test/test_module.py test/test_normalization.py test/test_os.py test/test_popen2.py test/test_poplib.py test/test_pyexpat.py test/test_re.py test/test_sax.py test/test_set.py test/test_smtplib.py test/test_socket.py test/test_socket_ssl.py test/test_softspace.py test/test_stringprep.py test/test_syntax.py test/test_tarfile.py test/test_telnetlib.py test/test_zipfile.py timeit.py urllib2.py Message-ID: <20070425063018.F1BED1E400B@bag.python.org> Author: neal.norwitz Date: Wed Apr 25 08:30:05 2007 New Revision: 54953 Modified: python/trunk/Lib/ctypes/__init__.py python/trunk/Lib/ctypes/test/test_numbers.py python/trunk/Lib/decimal.py python/trunk/Lib/ftplib.py python/trunk/Lib/pdb.py python/trunk/Lib/posixpath.py python/trunk/Lib/socket.py python/trunk/Lib/tempfile.py python/trunk/Lib/test/outstanding_bugs.py python/trunk/Lib/test/string_tests.py python/trunk/Lib/test/test_descr.py python/trunk/Lib/test/test_fileinput.py python/trunk/Lib/test/test_ftplib.py python/trunk/Lib/test/test_gc.py python/trunk/Lib/test/test_getopt.py python/trunk/Lib/test/test_httplib.py python/trunk/Lib/test/test_long_future.py python/trunk/Lib/test/test_minidom.py python/trunk/Lib/test/test_module.py python/trunk/Lib/test/test_normalization.py python/trunk/Lib/test/test_os.py python/trunk/Lib/test/test_popen2.py python/trunk/Lib/test/test_poplib.py python/trunk/Lib/test/test_pyexpat.py python/trunk/Lib/test/test_re.py python/trunk/Lib/test/test_sax.py python/trunk/Lib/test/test_set.py python/trunk/Lib/test/test_smtplib.py python/trunk/Lib/test/test_socket.py python/trunk/Lib/test/test_socket_ssl.py python/trunk/Lib/test/test_softspace.py python/trunk/Lib/test/test_stringprep.py python/trunk/Lib/test/test_syntax.py python/trunk/Lib/test/test_tarfile.py python/trunk/Lib/test/test_telnetlib.py python/trunk/Lib/test/test_zipfile.py python/trunk/Lib/timeit.py python/trunk/Lib/urllib2.py Log: Whitespace normalization. Ugh, we really need to do this more often. You might want to review this change as it's my first time. Be gentle. :-) Modified: python/trunk/Lib/ctypes/__init__.py ============================================================================== --- python/trunk/Lib/ctypes/__init__.py (original) +++ python/trunk/Lib/ctypes/__init__.py Wed Apr 25 08:30:05 2007 @@ -234,7 +234,7 @@ _check_size(c_void_p) class c_bool(_SimpleCData): - _type_ = "t" + _type_ = "t" # This cache maps types to pointers to them. _pointer_type_cache = {} Modified: python/trunk/Lib/ctypes/test/test_numbers.py ============================================================================== --- python/trunk/Lib/ctypes/test/test_numbers.py (original) +++ python/trunk/Lib/ctypes/test/test_numbers.py Wed Apr 25 08:30:05 2007 @@ -69,7 +69,7 @@ for t, (l, h) in zip(signed_types, signed_ranges): self.failUnlessEqual(t(l).value, l) self.failUnlessEqual(t(h).value, h) - + def test_bool_values(self): from operator import truth for t, v in zip(bool_types, bool_values): @@ -178,7 +178,7 @@ a[0] = '?' self.failUnlessEqual(v.value, a[0]) - + # array does not support c_bool / 't' # def test_bool_from_address(self): # from ctypes import c_bool Modified: python/trunk/Lib/decimal.py ============================================================================== --- python/trunk/Lib/decimal.py (original) +++ python/trunk/Lib/decimal.py Wed Apr 25 08:30:05 2007 @@ -2631,7 +2631,7 @@ 1) before use. If the increased precision needed for the intermediate calculations - exceeds the capabilities of the implementation then an Invalid + exceeds the capabilities of the implementation then an Invalid operation condition is raised. If, when raising to a negative power, an underflow occurs during the @@ -2725,7 +2725,7 @@ The result is the residue of the dividend after the operation of calculating integer division as described for divide-integer, rounded - to precision digits if necessary. The sign of the result, if + to precision digits if necessary. The sign of the result, if non-zero, is the same as that of the original dividend. This operation will fail under the same conditions as integer division @@ -2929,7 +2929,7 @@ if numdigits > (other_len + prec + 1 - tmp_len): # If the difference in adjusted exps is > prec+1, we know # other is insignificant, so might as well put a 1 after the - # precision (since this is only for addition). Also stops + # precision (since this is only for addition). Also stops # use of massive longs. extend = prec + 2 - tmp_len @@ -3098,7 +3098,7 @@ def _string2exact(s): """Return sign, n, p s.t. - + Float string value == -1**sign * n * 10**p exactly """ m = _parser(s) Modified: python/trunk/Lib/ftplib.py ============================================================================== --- python/trunk/Lib/ftplib.py (original) +++ python/trunk/Lib/ftplib.py Wed Apr 25 08:30:05 2007 @@ -84,7 +84,7 @@ meaning that no timeout will be set on any ftp socket(s) If a timeout is passed, then this is now the default timeout for all ftp socket operations for this instance. - + Then use self.connect() with optional host and port argument. To download a file, use ftp.retrlines('RETR ' + filename), @@ -112,7 +112,7 @@ self.timeout = timeout if host: self.connect(host) - if user: + if user: self.login(user, passwd, acct) def connect(self, host='', port=0, timeout=None): Modified: python/trunk/Lib/pdb.py ============================================================================== --- python/trunk/Lib/pdb.py (original) +++ python/trunk/Lib/pdb.py Wed Apr 25 08:30:05 2007 @@ -1149,7 +1149,7 @@ def _runscript(self, filename): # The script has to run in __main__ namespace (or imports from # __main__ will break). - # + # # So we clear up the __main__ and set several special variables # (this gets rid of pdb's globals and cleans old variables on restarts). import __main__ @@ -1158,7 +1158,7 @@ "__file__" : filename, "__builtins__": __builtins__, }) - + # When bdb sets tracing, a number of call and line events happens # BEFORE debugger even reaches user's code (and the exact sequence of # events depends on python version). So we take special measures to @@ -1168,7 +1168,7 @@ self.mainpyfile = self.canonic(filename) self._user_requested_quit = 0 statement = 'execfile( "%s")' % filename - self.run(statement) + self.run(statement) # Simplified interface Modified: python/trunk/Lib/posixpath.py ============================================================================== --- python/trunk/Lib/posixpath.py (original) +++ python/trunk/Lib/posixpath.py Wed Apr 25 08:30:05 2007 @@ -388,10 +388,10 @@ if not path: raise ValueError("no path specified") - + start_list = abspath(start).split(sep) path_list = abspath(path).split(sep) - + # Work out how much of the filepath is shared by start and path. i = len(commonprefix([start_list, path_list])) Modified: python/trunk/Lib/socket.py ============================================================================== --- python/trunk/Lib/socket.py (original) +++ python/trunk/Lib/socket.py Wed Apr 25 08:30:05 2007 @@ -24,7 +24,7 @@ ssl() -- secure socket layer support (only available if configured) socket.getdefaulttimeout() -- get the default timeout value socket.setdefaulttimeout() -- set the default timeout value -create_connection() -- connects to an address, with an optional timeout +create_connection() -- connects to an address, with an optional timeout [*] not available on all platforms! @@ -418,12 +418,12 @@ def create_connection(address, timeout=None): """Connect to address (host, port) with an optional timeout. - Provides access to socketobject timeout for higher-level - protocols. Passing a timeout will set the timeout on the + Provides access to socketobject timeout for higher-level + protocols. Passing a timeout will set the timeout on the socket instance (if not present, or passed as None, the default global timeout setting will be used). """ - + msg = "getaddrinfo returns an empty list" host, port = address for res in getaddrinfo(host, port, 0, SOCK_STREAM): @@ -435,7 +435,7 @@ sock.settimeout(timeout) sock.connect(sa) return sock - + except error, msg: if sock is not None: sock.close() Modified: python/trunk/Lib/tempfile.py ============================================================================== --- python/trunk/Lib/tempfile.py (original) +++ python/trunk/Lib/tempfile.py Wed Apr 25 08:30:05 2007 @@ -38,9 +38,9 @@ import Carbon.Folders as _Folders try: - from cStringIO import StringIO as _StringIO + from cStringIO import StringIO as _StringIO except: - from StringIO import StringIO as _StringIO + from StringIO import StringIO as _StringIO try: import fcntl as _fcntl @@ -510,7 +510,7 @@ newfile.seek(file.tell(), 0) self._rolled = True - + # file protocol def __iter__(self): return self._file.__iter__() Modified: python/trunk/Lib/test/outstanding_bugs.py ============================================================================== --- python/trunk/Lib/test/outstanding_bugs.py (original) +++ python/trunk/Lib/test/outstanding_bugs.py Wed Apr 25 08:30:05 2007 @@ -44,7 +44,7 @@ self.assertEquals(i, l) self.assertEquals(aptr, 1) self.assertEquals(bptr, 0) - + def test_main(): test_support.run_unittest(TestDifflibLongestMatch) Modified: python/trunk/Lib/test/string_tests.py ============================================================================== --- python/trunk/Lib/test/string_tests.py (original) +++ python/trunk/Lib/test/string_tests.py Wed Apr 25 08:30:05 2007 @@ -1096,9 +1096,9 @@ self.checkequal('Abc', 'abc', 'translate', table) self.checkequal('xyz', 'xyz', 'translate', table) self.checkequal('yz', 'xyz', 'translate', table, 'x') - self.checkequal('yx', 'zyzzx', 'translate', None, 'z') + self.checkequal('yx', 'zyzzx', 'translate', None, 'z') self.checkequal('zyzzx', 'zyzzx', 'translate', None, '') - self.checkequal('zyzzx', 'zyzzx', 'translate', None) + self.checkequal('zyzzx', 'zyzzx', 'translate', None) self.checkraises(ValueError, 'xyz', 'translate', 'too short', 'strip') self.checkraises(ValueError, 'xyz', 'translate', 'too short') Modified: python/trunk/Lib/test/test_descr.py ============================================================================== --- python/trunk/Lib/test/test_descr.py (original) +++ python/trunk/Lib/test/test_descr.py Wed Apr 25 08:30:05 2007 @@ -1248,7 +1248,7 @@ c.abc = 5 vereq(c.abc, 5) - # _unicode_to_string used to modify slots in certain circumstances + # _unicode_to_string used to modify slots in certain circumstances slots = (unicode("foo"), unicode("bar")) class C(object): __slots__ = slots @@ -1263,7 +1263,7 @@ except (TypeError, UnicodeEncodeError): pass else: - raise TestFailed, "[unichr(128)] slots not caught" + raise TestFailed, "[unichr(128)] slots not caught" # Test leaks class Counted(object): Modified: python/trunk/Lib/test/test_fileinput.py ============================================================================== --- python/trunk/Lib/test/test_fileinput.py (original) +++ python/trunk/Lib/test/test_fileinput.py Wed Apr 25 08:30:05 2007 @@ -27,7 +27,7 @@ def remove_tempfiles(*names): for name in names: safe_unlink(name) - + class BufferSizesTests(unittest.TestCase): def test_buffer_sizes(self): # First, run the tests with default and teeny buffer size. @@ -40,10 +40,10 @@ self.buffer_size_test(t1, t2, t3, t4, bs, round) finally: remove_tempfiles(t1, t2, t3, t4) - + def buffer_size_test(self, t1, t2, t3, t4, bs=0, round=0): pat = re.compile(r'LINE (\d+) OF FILE (\d+)') - + start = 1 + round*6 if verbose: print '%s. Simple iteration (bs=%s)' % (start+0, bs) @@ -117,7 +117,7 @@ self.assertNotEqual(m, None) self.assertEqual(int(m.group(1)), fi.filelineno()) fi.close() - + class FileInputTests(unittest.TestCase): def test_zero_byte_files(self): try: @@ -126,13 +126,13 @@ t3 = writeTmp(3, ["The only line there is.\n"]) t4 = writeTmp(4, [""]) fi = FileInput(files=(t1, t2, t3, t4)) - + line = fi.readline() self.assertEqual(line, 'The only line there is.\n') self.assertEqual(fi.lineno(), 1) self.assertEqual(fi.filelineno(), 1) self.assertEqual(fi.filename(), t3) - + line = fi.readline() self.failIf(line) self.assertEqual(fi.lineno(), 1) @@ -220,6 +220,6 @@ def test_main(): run_unittest(BufferSizesTests, FileInputTests) - + if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_ftplib.py ============================================================================== --- python/trunk/Lib/test/test_ftplib.py (original) +++ python/trunk/Lib/test/test_ftplib.py Wed Apr 25 08:30:05 2007 @@ -24,7 +24,7 @@ evt.set() class GeneralTests(TestCase): - + def setUp(self): ftplib.FTP.port = 9091 self.evt = threading.Event() @@ -41,13 +41,13 @@ # connects ftp = ftplib.FTP("localhost") ftp.sock.close() - + def testTimeoutDefault(self): # default ftp = ftplib.FTP("localhost") self.assertTrue(ftp.sock.gettimeout() is None) ftp.sock.close() - + def testTimeoutValue(self): # a value ftp = ftplib.FTP("localhost", timeout=30) Modified: python/trunk/Lib/test/test_gc.py ============================================================================== --- python/trunk/Lib/test/test_gc.py (original) +++ python/trunk/Lib/test/test_gc.py Wed Apr 25 08:30:05 2007 @@ -6,7 +6,7 @@ ### Support code ############################################################################### - + # Bug 1055820 has several tests of longstanding bugs involving weakrefs and # cyclic gc. @@ -32,9 +32,9 @@ self.wr = weakref.ref(C1055820(666), it_happened) -### Tests +### Tests ############################################################################### - + class GCTests(unittest.TestCase): def test_list(self): l = [] @@ -259,7 +259,7 @@ Ouch.n = Ouch.n + 1 if Ouch.n % 17 == 0: gc.collect() - + # "trashcan" is a hack to prevent stack overflow when deallocating # very deeply nested tuples etc. It works in part by abusing the # type pointer and refcount fields, and that can yield horrible @@ -292,7 +292,7 @@ def __getattr__(self, someattribute): del self.attr raise AttributeError - + a = Boom() b = Boom() a.attr = b @@ -321,7 +321,7 @@ if self.x > 1: del self.attr raise AttributeError - + a = Boom2() b = Boom2() a.attr = b @@ -346,7 +346,7 @@ def __getattr__(self, someattribute): del self.attr raise AttributeError - + a = Boom_New() b = Boom_New() a.attr = b @@ -368,7 +368,7 @@ if self.x > 1: del self.attr raise AttributeError - + a = Boom2_New() b = Boom2_New() a.attr = b @@ -430,10 +430,10 @@ class GCTogglingTests(unittest.TestCase): def setUp(self): gc.enable() - + def tearDown(self): gc.disable() - + def test_bug1055820c(self): # Corresponds to temp2c.py in the bug report. This is pretty # elaborate. @@ -591,6 +591,6 @@ assert gc.isenabled() if not enabled: gc.disable() - + if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_getopt.py ============================================================================== --- python/trunk/Lib/test/test_getopt.py (original) +++ python/trunk/Lib/test/test_getopt.py Wed Apr 25 08:30:05 2007 @@ -15,15 +15,15 @@ if self.old_posixly_correct is not sentinel: del os.environ["POSIXLY_CORRECT"] - def tearDown(self): + def tearDown(self): if self.old_posixly_correct is sentinel: os.environ.pop("POSIXLY_CORRECT", None) else: os.environ["POSIXLY_CORRECT"] = self.old_posixly_correct - + def assertError(self, *args, **kwargs): self.assertRaises(getopt.GetoptError, *args, **kwargs) - + def test_short_has_arg(self): self.failUnless(getopt.short_has_arg('a', 'a:')) self.failIf(getopt.short_has_arg('a', 'a')) @@ -33,15 +33,15 @@ has_arg, option = getopt.long_has_args('abc', ['abc=']) self.failUnless(has_arg) self.assertEqual(option, 'abc') - + has_arg, option = getopt.long_has_args('abc', ['abc']) self.failIf(has_arg) self.assertEqual(option, 'abc') - + has_arg, option = getopt.long_has_args('abc', ['abcd']) self.failIf(has_arg) self.assertEqual(option, 'abcd') - + self.assertError(getopt.long_has_args, 'abc', ['def']) self.assertError(getopt.long_has_args, 'abc', []) self.assertError(getopt.long_has_args, 'abc', ['abcd','abcde']) @@ -50,23 +50,23 @@ opts, args = getopt.do_shorts([], 'a', 'a', []) self.assertEqual(opts, [('-a', '')]) self.assertEqual(args, []) - + opts, args = getopt.do_shorts([], 'a1', 'a:', []) self.assertEqual(opts, [('-a', '1')]) self.assertEqual(args, []) - + #opts, args = getopt.do_shorts([], 'a=1', 'a:', []) #self.assertEqual(opts, [('-a', '1')]) #self.assertEqual(args, []) - + opts, args = getopt.do_shorts([], 'a', 'a:', ['1']) self.assertEqual(opts, [('-a', '1')]) self.assertEqual(args, []) - + opts, args = getopt.do_shorts([], 'a', 'a:', ['1', '2']) self.assertEqual(opts, [('-a', '1')]) self.assertEqual(args, ['2']) - + self.assertError(getopt.do_shorts, [], 'a1', 'a', []) self.assertError(getopt.do_shorts, [], 'a', 'a:', []) @@ -74,26 +74,26 @@ opts, args = getopt.do_longs([], 'abc', ['abc'], []) self.assertEqual(opts, [('--abc', '')]) self.assertEqual(args, []) - + opts, args = getopt.do_longs([], 'abc=1', ['abc='], []) self.assertEqual(opts, [('--abc', '1')]) self.assertEqual(args, []) - + opts, args = getopt.do_longs([], 'abc=1', ['abcd='], []) self.assertEqual(opts, [('--abcd', '1')]) self.assertEqual(args, []) - + opts, args = getopt.do_longs([], 'abc', ['ab', 'abc', 'abcd'], []) self.assertEqual(opts, [('--abc', '')]) self.assertEqual(args, []) - + # Much like the preceding, except with a non-alpha character ("-") in # option name that precedes "="; failed in # http://python.org/sf/126863 opts, args = getopt.do_longs([], 'foo=42', ['foo-bar', 'foo=',], []) self.assertEqual(opts, [('--foo', '42')]) self.assertEqual(args, []) - + self.assertError(getopt.do_longs, [], 'abc=1', ['abc'], []) self.assertError(getopt.do_longs, [], 'abc', ['abc='], []) @@ -117,18 +117,18 @@ def test_gnu_getopt(self): # Test handling of GNU style scanning mode. cmdline = ['-a', 'arg1', '-b', '1', '--alpha', '--beta=2'] - + # GNU style opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) self.assertEqual(args, ['arg1']) self.assertEqual(opts, [('-a', ''), ('-b', '1'), ('--alpha', ''), ('--beta', '2')]) - + # Posix style via + opts, args = getopt.gnu_getopt(cmdline, '+ab:', ['alpha', 'beta=']) self.assertEqual(opts, [('-a', '')]) self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2']) - + # Posix style via POSIXLY_CORRECT os.environ["POSIXLY_CORRECT"] = "1" opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) @@ -166,7 +166,7 @@ >>> args ['a1', 'a2'] """ - + import new m = new.module("libreftest", s) run_doctest(m, verbose) @@ -174,6 +174,6 @@ def test_main(): run_unittest(GetoptTests) - + if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_httplib.py ============================================================================== --- python/trunk/Lib/test/test_httplib.py (original) +++ python/trunk/Lib/test/test_httplib.py Wed Apr 25 08:30:05 2007 @@ -154,7 +154,7 @@ HOST = "localhost" class TimeoutTest(TestCase): - + def setUp(self): self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -175,7 +175,7 @@ httpConn.connect() self.assertTrue(httpConn.sock.gettimeout() is None) httpConn.close() - + # a value httpConn = httplib.HTTPConnection(HOST, PORT, timeout=30) httpConn.connect() Modified: python/trunk/Lib/test/test_long_future.py ============================================================================== --- python/trunk/Lib/test/test_long_future.py (original) +++ python/trunk/Lib/test/test_long_future.py Wed Apr 25 08:30:05 2007 @@ -50,6 +50,6 @@ def test_main(): run_unittest(TrueDivisionTests) - + if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_minidom.py ============================================================================== --- python/trunk/Lib/test/test_minidom.py (original) +++ python/trunk/Lib/test/test_minidom.py Wed Apr 25 08:30:05 2007 @@ -72,25 +72,25 @@ # are needed print len(Node.allnodes) Node.allnodes = {} - + def confirm(self, test, testname = "Test"): self.assertTrue(test, testname) - + def checkWholeText(self, node, s): t = node.wholeText self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t))) - + def testParseFromFile(self): dom = parse(StringIO(open(tstfile).read())) dom.unlink() self.confirm(isinstance(dom,Document)) - + def testGetElementsByTagName(self): dom = parse(tstfile) self.confirm(dom.getElementsByTagName("LI") == \ dom.documentElement.getElementsByTagName("LI")) dom.unlink() - + def testInsertBefore(self): dom = parseString("") root = dom.documentElement @@ -129,11 +129,11 @@ and root.childNodes.item(3) is nelem and nelem2.nextSibling is nelem and nelem.previousSibling is nelem2 - and root.toxml() == + and root.toxml() == "" , "testInsertBefore -- node properly placed in tree") dom.unlink() - + def _create_fragment_test_nodes(self): dom = parseString("") orig = dom.createTextNode("original") @@ -146,11 +146,11 @@ frag.appendChild(c2) frag.appendChild(c3) return dom, orig, c1, c2, c3, frag - + def testInsertBeforeFragment(self): dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() dom.documentElement.insertBefore(frag, None) - self.confirm(tuple(dom.documentElement.childNodes) == + self.confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), "insertBefore(, None)") frag.unlink() @@ -158,28 +158,28 @@ dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() dom.documentElement.insertBefore(frag, orig) - self.confirm(tuple(dom.documentElement.childNodes) == + self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig), "insertBefore(, orig)") frag.unlink() dom.unlink() - + def testAppendChild(self): dom = parse(tstfile) dom.documentElement.appendChild(dom.createComment(u"Hello")) self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment") self.confirm(dom.documentElement.childNodes[-1].data == "Hello") dom.unlink() - + def testAppendChildFragment(self): dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() dom.documentElement.appendChild(frag) - self.confirm(tuple(dom.documentElement.childNodes) == + self.confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), "appendChild()") frag.unlink() dom.unlink() - + def testReplaceChildFragment(self): dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() dom.documentElement.replaceChild(frag, orig) @@ -188,28 +188,28 @@ "replaceChild()") frag.unlink() dom.unlink() - + def testLegalChildren(self): dom = Document() elem = dom.createElement('element') text = dom.createTextNode('text') self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text) - + dom.appendChild(elem) - self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text, + self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text, elem) - self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text, + self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text, elem) - + nodemap = elem.attributes - self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem, + self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem, text) - self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS, + self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS, text) - + elem.appendChild(text) dom.unlink() - + def testNamedNodeMapSetItem(self): dom = Document() elem = dom.createElement('element') @@ -226,24 +226,24 @@ "NamedNodeMap.__setitem__() sets nodeValue") elem.unlink() dom.unlink() - + def testNonZero(self): dom = parse(tstfile) self.confirm(dom)# should not be zero dom.appendChild(dom.createComment("foo")) self.confirm(not dom.childNodes[-1].childNodes) dom.unlink() - + def testUnlink(self): dom = parse(tstfile) dom.unlink() - + def testElement(self): dom = Document() dom.appendChild(dom.createElement("abc")) self.confirm(dom.documentElement) dom.unlink() - + def testAAA(self): dom = parseString("") el = dom.documentElement @@ -255,7 +255,7 @@ self.confirm(a.ownerElement is dom.documentElement, "setAttribute() sets ownerElement") dom.unlink() - + def testAAB(self): dom = parseString("") el = dom.documentElement @@ -263,49 +263,49 @@ el.setAttribute("spam", "jam2") self.confirm(el.toxml() == '', "testAAB") dom.unlink() - + def testAddAttr(self): dom = Document() child = dom.appendChild(dom.createElement("abc")) - + child.setAttribute("def", "ghi") self.confirm(child.getAttribute("def") == "ghi") self.confirm(child.attributes["def"].value == "ghi") - + child.setAttribute("jkl", "mno") self.confirm(child.getAttribute("jkl") == "mno") self.confirm(child.attributes["jkl"].value == "mno") - + self.confirm(len(child.attributes) == 2) - + child.setAttribute("def", "newval") self.confirm(child.getAttribute("def") == "newval") self.confirm(child.attributes["def"].value == "newval") - + self.confirm(len(child.attributes) == 2) dom.unlink() - + def testDeleteAttr(self): dom = Document() child = dom.appendChild(dom.createElement("abc")) - + self.confirm(len(child.attributes) == 0) child.setAttribute("def", "ghi") self.confirm(len(child.attributes) == 1) del child.attributes["def"] self.confirm(len(child.attributes) == 0) dom.unlink() - + def testRemoveAttr(self): dom = Document() child = dom.appendChild(dom.createElement("abc")) - + child.setAttribute("def", "ghi") self.confirm(len(child.attributes) == 1) child.removeAttribute("def") self.confirm(len(child.attributes) == 0) dom.unlink() - + def testRemoveAttrNS(self): dom = Document() child = dom.appendChild( @@ -317,7 +317,7 @@ child.removeAttributeNS("http://www.python.org", "abcattr") self.confirm(len(child.attributes) == 1) dom.unlink() - + def testRemoveAttributeNode(self): dom = Document() child = dom.appendChild(dom.createElement("foo")) @@ -328,7 +328,7 @@ self.confirm(len(child.attributes) == 0 and child.getAttributeNode("spam") is None) dom.unlink() - + def testChangeAttr(self): dom = parseString("") el = dom.documentElement @@ -366,26 +366,26 @@ and el.attributes["spam2"].nodeValue == "bam2" and el.getAttribute("spam2") == "bam2") dom.unlink() - + def testGetAttrList(self): pass - + def testGetAttrValues(self): pass - + def testGetAttrLength(self): pass - + def testGetAttribute(self): pass - + def testGetAttributeNS(self): pass - + def testGetAttributeNode(self): pass - + def testGetElementsByTagNameNS(self): d=""" """ dom = parseString(d) - elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", + elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem") self.confirm(len(elems) == 1 and elems[0].namespaceURI == "http://pyxml.sf.net/minidom" @@ -394,12 +394,12 @@ and elems[0].tagName == "minidom:myelem" and elems[0].nodeName == "minidom:myelem") dom.unlink() - - def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri, + + def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri, lname): nodelist = doc.getElementsByTagNameNS(nsuri, lname) self.confirm(len(nodelist) == 0) - + def testGetEmptyNodeListFromElementsByTagNameNS(self): doc = parseString('') self.get_empty_nodelist_from_elements_by_tagName_ns_helper( @@ -408,7 +408,7 @@ doc, '*', 'splat') self.get_empty_nodelist_from_elements_by_tagName_ns_helper( doc, 'http://xml.python.org/namespaces/a', '*') - + doc = parseString('') self.get_empty_nodelist_from_elements_by_tagName_ns_helper( doc, "http://xml.python.org/splat", "not-there") @@ -416,7 +416,7 @@ doc, "*", "not-there") self.get_empty_nodelist_from_elements_by_tagName_ns_helper( doc, "http://somewhere.else.net/not-there", "e") - + def testElementReprAndStr(self): dom = Document() el = dom.appendChild(dom.createElement("abc")) @@ -424,7 +424,7 @@ string2 = str(el) self.confirm(string1 == string2) dom.unlink() - + def testElementReprAndStrUnicode(self): dom = Document() el = dom.appendChild(dom.createElement(u"abc")) @@ -432,7 +432,7 @@ string2 = str(el) self.confirm(string1 == string2) dom.unlink() - + def testElementReprAndStrUnicodeNS(self): dom = Document() el = dom.appendChild( @@ -442,30 +442,30 @@ self.confirm(string1 == string2) self.confirm(string1.find("slash:abc") != -1) dom.unlink() - + def testAttributeRepr(self): dom = Document() el = dom.appendChild(dom.createElement(u"abc")) node = el.setAttribute("abc", "def") self.confirm(str(node) == repr(node)) dom.unlink() - + def testTextNodeRepr(self): pass - + def testWriteXML(self): str = '' dom = parseString(str) domstr = dom.toxml() dom.unlink() self.confirm(str == domstr) - + def testAltNewline(self): str = '\n\n' dom = parseString(str) domstr = dom.toprettyxml(newl="\r\n") dom.unlink() self.confirm(domstr == str.replace("\n", "\r\n")) - + def testProcessingInstruction(self): dom = parseString('') pi = dom.documentElement.firstChild @@ -480,15 +480,15 @@ and pi.lastChild is None and pi.localName is None and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE) - + def testProcessingInstructionRepr(self): pass - + def testTextRepr(self): pass - + def testWriteText(self): pass - + def testDocumentElement(self): pass - + def testTooManyDocumentElements(self): doc = parseString("") elem = doc.createElement("extra") @@ -496,27 +496,27 @@ self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem) elem.unlink() doc.unlink() - + def testCreateElementNS(self): pass - + def testCreateAttributeNS(self): pass - + def testParse(self): pass - + def testParseString(self): pass - + def testComment(self): pass - + def testAttrListItem(self): pass - + def testAttrListItems(self): pass - + def testAttrListItemNS(self): pass - + def testAttrListKeys(self): pass - + def testAttrListKeysNS(self): pass - + def testRemoveNamedItem(self): doc = parseString("") e = doc.documentElement @@ -525,7 +525,7 @@ a2 = attrs.removeNamedItem("a") self.confirm(a1.isSameNode(a2)) self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a") - + def testRemoveNamedItemNS(self): doc = parseString("") e = doc.documentElement @@ -533,33 +533,33 @@ a1 = e.getAttributeNodeNS("http://xml.python.org/", "b") a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b") self.confirm(a1.isSameNode(a2)) - self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS, + self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS, "http://xml.python.org/", "b") - + def testAttrListValues(self): pass - + def testAttrListLength(self): pass - + def testAttrList__getitem__(self): pass - + def testAttrList__setitem__(self): pass - + def testSetAttrValueandNodeValue(self): pass - + def testParseElement(self): pass - + def testParseAttributes(self): pass - + def testParseElementNamespaces(self): pass - + def testParseAttributeNamespaces(self): pass - + def testParseProcessingInstructions(self): pass - + def testChildNodes(self): pass - + def testFirstChild(self): pass - + def testHasChildNodes(self): pass def _testCloneElementCopiesAttributes(self, e1, e2, test): @@ -581,7 +581,7 @@ , "clone of attribute node has proper attribute values") self.confirm(a2.ownerElement is e2, "clone of attribute node correctly owned") - + def _setupCloneElement(self, deep): dom = parseString("") root = dom.documentElement @@ -593,7 +593,7 @@ root.setAttribute("attr", "NEW VALUE") root.setAttribute("added", "VALUE") return dom, clone - + def testCloneElementShallow(self): dom, clone = self._setupCloneElement(0) self.confirm(len(clone.childNodes) == 0 @@ -602,7 +602,7 @@ and clone.toxml() == '' , "testCloneElementShallow") dom.unlink() - + def testCloneElementDeep(self): dom, clone = self._setupCloneElement(1) self.confirm(len(clone.childNodes) == 1 @@ -711,25 +711,25 @@ doc1 = parseString("") doc2 = parseString("") self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep) - + def testImportDocumentShallow(self): self.check_import_document(0, "testImportDocumentShallow") - + def testImportDocumentDeep(self): self.check_import_document(1, "testImportDocumentDeep") - + def testImportDocumentTypeShallow(self): src = create_doc_with_doctype() target = create_doc_without_doctype() - self.assertRaises(xml.dom.NotSupportedErr, target.importNode, + self.assertRaises(xml.dom.NotSupportedErr, target.importNode, src.doctype, 0) - + def testImportDocumentTypeDeep(self): src = create_doc_with_doctype() target = create_doc_without_doctype() - self.assertRaises(xml.dom.NotSupportedErr, target.importNode, + self.assertRaises(xml.dom.NotSupportedErr, target.importNode, src.doctype, 1) - + # Testing attribute clones uses a helper, and should always be deep, # even if the argument to cloneNode is false. def check_clone_attribute(self, deep, testName): @@ -745,13 +745,13 @@ testName + ": ownerDocument does not match") self.confirm(clone.specified, testName + ": cloned attribute must have specified == True") - + def testCloneAttributeShallow(self): self.check_clone_attribute(0, "testCloneAttributeShallow") - + def testCloneAttributeDeep(self): self.check_clone_attribute(1, "testCloneAttributeDeep") - + def check_clone_pi(self, deep, testName): doc = parseString("") pi = doc.firstChild @@ -759,10 +759,10 @@ clone = pi.cloneNode(deep) self.confirm(clone.target == pi.target and clone.data == pi.data) - + def testClonePIShallow(self): self.check_clone_pi(0, "testClonePIShallow") - + def testClonePIDeep(self): self.check_clone_pi(1, "testClonePIDeep") @@ -772,7 +772,7 @@ root.appendChild(doc.createTextNode("first")) root.appendChild(doc.createTextNode("second")) self.confirm(len(root.childNodes) == 2 - and root.childNodes.length == 2, + and root.childNodes.length == 2, "testNormalize -- preparation") doc.normalize() self.confirm(len(root.childNodes) == 1 @@ -781,7 +781,7 @@ and root.firstChild.data == "firstsecond" , "testNormalize -- result") doc.unlink() - + doc = parseString("") root = doc.documentElement root.appendChild(doc.createTextNode("")) @@ -790,21 +790,21 @@ and root.childNodes.length == 0, "testNormalize -- single empty node removed") doc.unlink() - + def testSiblings(self): doc = parseString("text?") root = doc.documentElement (pi, text, elm) = root.childNodes - + self.confirm(pi.nextSibling is text and pi.previousSibling is None and text.nextSibling is elm and text.previousSibling is pi and elm.nextSibling is None and elm.previousSibling is text, "testSiblings") - + doc.unlink() - + def testParents(self): doc = parseString( "") @@ -812,14 +812,14 @@ elm1 = root.childNodes[0] (elm2a, elm2b) = elm1.childNodes elm3 = elm2b.childNodes[0] - + self.confirm(root.parentNode is doc and elm1.parentNode is root and elm2a.parentNode is elm1 and elm2b.parentNode is elm1 and elm3.parentNode is elm2b, "testParents") doc.unlink() - + def testNodeListItem(self): doc = parseString("") children = doc.childNodes @@ -831,10 +831,10 @@ and docelem.childNodes.item(0).childNodes.item(0) is None, "test NodeList.item()") doc.unlink() - + def testSAX2DOM(self): from xml.dom import pulldom - + sax2dom = pulldom.SAX2DOM() sax2dom.startDocument() sax2dom.startElement("doc", {}) @@ -845,12 +845,12 @@ sax2dom.characters("text") sax2dom.endElement("doc") sax2dom.endDocument() - + doc = sax2dom.document root = doc.documentElement (text1, elm1, text2) = root.childNodes text3 = elm1.childNodes[0] - + self.confirm(text1.previousSibling is None and text1.nextSibling is elm1 and elm1.previousSibling is text1 and @@ -859,28 +859,28 @@ text2.nextSibling is None and text3.previousSibling is None and text3.nextSibling is None, "testSAX2DOM - siblings") - + self.confirm(root.parentNode is doc and text1.parentNode is root and elm1.parentNode is root and text2.parentNode is root and text3.parentNode is elm1, "testSAX2DOM - parents") doc.unlink() - + def testEncodings(self): doc = parseString('') self.confirm(doc.toxml() == u'\u20ac' - and doc.toxml('utf-8') == + and doc.toxml('utf-8') == '\xe2\x82\xac' - and doc.toxml('iso-8859-15') == + and doc.toxml('iso-8859-15') == '\xa4', "testEncodings - encoding EURO SIGN") - - # Verify that character decoding errors throw exceptions instead + + # Verify that character decoding errors throw exceptions instead # of crashing - self.assertRaises(UnicodeDecodeError, parseString, + self.assertRaises(UnicodeDecodeError, parseString, 'Comment \xe7a va ? Tr\xe8s bien ?') - + doc.unlink() class UserDataHandler: @@ -889,7 +889,7 @@ dst.setUserData(key, data + 1, self) src.setUserData(key, None, None) self.called = 1 - + def testUserData(self): dom = Document() n = dom.createElement('e') @@ -903,7 +903,7 @@ n.setUserData("foo", None, None) self.confirm(n.getUserData("foo") is None) self.confirm(n.getUserData("bar") == 13) - + handler = self.UserDataHandler() n.setUserData("bar", 12, handler) c = n.cloneNode(1) @@ -916,18 +916,18 @@ def checkRenameNodeSharedConstraints(self, doc, node): # Make sure illegal NS usage is detected: - self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node, + self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node, "http://xml.python.org/ns", "xmlns:foo") doc2 = parseString("") - self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node, + self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node, xml.dom.EMPTY_NAMESPACE, "foo") - + def testRenameAttribute(self): doc = parseString("") elem = doc.documentElement attrmap = elem.attributes attr = elem.attributes['a'] - + # Simple renaming attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b") self.confirm(attr.name == "b" @@ -941,7 +941,7 @@ and attrmap["b"].isSameNode(attr) and attr.ownerDocument.isSameNode(doc) and attr.ownerElement.isSameNode(elem)) - + # Rename to have a namespace, no prefix attr = doc.renameNode(attr, "http://xml.python.org/ns", "c") self.confirm(attr.name == "c" @@ -957,7 +957,7 @@ "http://xml.python.org/ns", "c").isSameNode(attr) and attrmap["c"].isSameNode(attr) and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr)) - + # Rename to have a namespace, with prefix attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d") self.confirm(attr.name == "p:d" @@ -976,7 +976,7 @@ "http://xml.python.org/ns2", "d").isSameNode(attr) and attrmap["p:d"].isSameNode(attr) and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr)) - + # Rename back to a simple non-NS node attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e") self.confirm(attr.name == "e" @@ -994,15 +994,15 @@ and elem.getAttributeNode("e").isSameNode(attr) and attrmap["e"].isSameNode(attr)) - self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr, + self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr, "http://xml.python.org/ns", "xmlns") self.checkRenameNodeSharedConstraints(doc, attr) doc.unlink() - + def testRenameElement(self): doc = parseString("") elem = doc.documentElement - + # Simple renaming elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a") self.confirm(elem.tagName == "a" @@ -1011,7 +1011,7 @@ and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE and elem.prefix is None and elem.ownerDocument.isSameNode(doc)) - + # Rename to have a namespace, no prefix elem = doc.renameNode(elem, "http://xml.python.org/ns", "b") self.confirm(elem.tagName == "b" @@ -1020,7 +1020,7 @@ and elem.namespaceURI == "http://xml.python.org/ns" and elem.prefix is None and elem.ownerDocument.isSameNode(doc)) - + # Rename to have a namespace, with prefix elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c") self.confirm(elem.tagName == "p:c" @@ -1029,7 +1029,7 @@ and elem.namespaceURI == "http://xml.python.org/ns2" and elem.prefix == "p" and elem.ownerDocument.isSameNode(doc)) - + # Rename back to a simple non-NS node elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d") self.confirm(elem.tagName == "d" @@ -1038,17 +1038,17 @@ and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE and elem.prefix is None and elem.ownerDocument.isSameNode(doc)) - + self.checkRenameNodeSharedConstraints(doc, elem) doc.unlink() - + def testRenameOther(self): # We have to create a comment node explicitly since not all DOM # builders used with minidom add comments to the DOM. doc = xml.dom.minidom.getDOMImplementation().createDocument( xml.dom.EMPTY_NAMESPACE, "e", None) node = doc.createComment("comment") - self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node, + self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node, xml.dom.EMPTY_NAMESPACE, "foo") doc.unlink() @@ -1057,13 +1057,13 @@ elem = doc.documentElement text = elem.childNodes[0] self.assertEquals(text.nodeType, Node.TEXT_NODE) - + self.checkWholeText(text, "a") elem.appendChild(doc.createTextNode("b")) self.checkWholeText(text, "ab") elem.insertBefore(doc.createCDATASection("c"), text) self.checkWholeText(text, "cab") - + # make sure we don't cross other nodes splitter = doc.createComment("comment") elem.appendChild(splitter) @@ -1071,23 +1071,23 @@ elem.appendChild(text2) self.checkWholeText(text, "cab") self.checkWholeText(text2, "d") - + x = doc.createElement("x") elem.replaceChild(x, splitter) splitter = x self.checkWholeText(text, "cab") self.checkWholeText(text2, "d") - + x = doc.createProcessingInstruction("y", "z") elem.replaceChild(x, splitter) splitter = x self.checkWholeText(text, "cab") self.checkWholeText(text2, "d") - + elem.removeChild(splitter) self.checkWholeText(text, "cabd") self.checkWholeText(text2, "cabd") - + def testPatch1094164(self): doc = parseString("") elem = doc.documentElement @@ -1096,7 +1096,7 @@ # Check that replacing a child with itself leaves the tree unchanged elem.replaceChild(e, e) self.confirm(e.parentNode is elem, "After replaceChild()") - + def testReplaceWholeText(self): def setup(): doc = parseString("ad") @@ -1107,25 +1107,25 @@ elem.insertBefore(doc.createTextNode("b"), splitter) elem.insertBefore(doc.createCDATASection("c"), text1) return doc, elem, text1, splitter, text2 - + doc, elem, text1, splitter, text2 = setup() text = text1.replaceWholeText("new content") self.checkWholeText(text, "new content") self.checkWholeText(text2, "d") self.confirm(len(elem.childNodes) == 3) - + doc, elem, text1, splitter, text2 = setup() text = text2.replaceWholeText("new content") self.checkWholeText(text, "new content") self.checkWholeText(text1, "cab") self.confirm(len(elem.childNodes) == 5) - + doc, elem, text1, splitter, text2 = setup() text = text1.replaceWholeText("") self.checkWholeText(text2, "d") self.confirm(text is None and len(elem.childNodes) == 2) - + def testSchemaType(self): doc = parseString( "") e = doc.documentElement @@ -1189,7 +1189,7 @@ doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") self.confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) - + def testSetIdAttributeNS(self): NS1 = "http://xml.python.org/ns1" NS2 = "http://xml.python.org/ns2" @@ -1309,6 +1309,6 @@ def test_main(): run_unittest(MinidomTest) - + if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_module.py ============================================================================== --- python/trunk/Lib/test/test_module.py (original) +++ python/trunk/Lib/test/test_module.py Wed Apr 25 08:30:05 2007 @@ -56,6 +56,6 @@ def test_main(): run_unittest(ModuleTests) - + if __name__ == '__main__': test_main() Modified: python/trunk/Lib/test/test_normalization.py ============================================================================== --- python/trunk/Lib/test/test_normalization.py (original) +++ python/trunk/Lib/test/test_normalization.py Wed Apr 25 08:30:05 2007 @@ -29,7 +29,7 @@ if x > sys.maxunicode: raise RangeError return u"".join([unichr(x) for x in data]) - + class NormalizationTest(unittest.TestCase): def test_main(self): part1_data = {} Modified: python/trunk/Lib/test/test_os.py ============================================================================== --- python/trunk/Lib/test/test_os.py (original) +++ python/trunk/Lib/test/test_os.py Wed Apr 25 08:30:05 2007 @@ -281,7 +281,7 @@ from os.path import join # Build: - # TESTFN/ + # TESTFN/ # TEST1/ a file kid and two directory kids # tmp1 # SUB1/ a file kid and a directory kid Modified: python/trunk/Lib/test/test_popen2.py ============================================================================== --- python/trunk/Lib/test/test_popen2.py (original) +++ python/trunk/Lib/test/test_popen2.py Wed Apr 25 08:30:05 2007 @@ -45,7 +45,7 @@ inst.wait() popen2._cleanup() self.assertFalse(popen2._active, "_active not empty") - reap_children() + reap_children() def validate_output(self, teststr, expected_out, r, w, e=None): w.write(teststr) @@ -57,7 +57,7 @@ if e is not None: got = e.read() self.assertFalse(got, "unexpected %r on stderr" % got) - + def test_popen2(self): r, w = popen2.popen2(self.cmd) self.validate_output(self.teststr, self.expected, r, w) @@ -84,7 +84,7 @@ w, r, e = os.popen3(self.cmd) self.validate_output(self.teststr, self.expected, r, w, e) - + def test_main(): run_unittest(Popen2Test) Modified: python/trunk/Lib/test/test_poplib.py ============================================================================== --- python/trunk/Lib/test/test_poplib.py (original) +++ python/trunk/Lib/test/test_poplib.py Wed Apr 25 08:30:05 2007 @@ -25,7 +25,7 @@ evt.set() class GeneralTests(TestCase): - + def setUp(self): self.evt = threading.Event() threading.Thread(target=server, args=(self.evt,)).start() @@ -38,13 +38,13 @@ # connects pop = poplib.POP3("localhost", 9091) pop.sock.close() - + def testTimeoutDefault(self): # default pop = poplib.POP3("localhost", 9091) self.assertTrue(pop.sock.gettimeout() is None) pop.sock.close() - + def testTimeoutValue(self): # a value pop = poplib.POP3("localhost", 9091, timeout=30) Modified: python/trunk/Lib/test/test_pyexpat.py ============================================================================== --- python/trunk/Lib/test/test_pyexpat.py (original) +++ python/trunk/Lib/test/test_pyexpat.py Wed Apr 25 08:30:05 2007 @@ -19,12 +19,12 @@ [2, 1], [0, 0], ] - + def test_returns_unicode(self): for x, y in self.set_get_pairs: self.parser.returns_unicode = x self.assertEquals(self.parser.returns_unicode, y) - + def test_ordered_attributes(self): for x, y in self.set_get_pairs: self.parser.ordered_attributes = x @@ -64,57 +64,57 @@ class Outputter: def __init__(self): self.out = [] - + def StartElementHandler(self, name, attrs): - self.out.append('Start element: ' + repr(name) + ' ' + + self.out.append('Start element: ' + repr(name) + ' ' + sortdict(attrs)) - + def EndElementHandler(self, name): self.out.append('End element: ' + repr(name)) - + def CharacterDataHandler(self, data): data = data.strip() if data: self.out.append('Character data: ' + repr(data)) - + def ProcessingInstructionHandler(self, target, data): self.out.append('PI: ' + repr(target) + ' ' + repr(data)) - + def StartNamespaceDeclHandler(self, prefix, uri): self.out.append('NS decl: ' + repr(prefix) + ' ' + repr(uri)) - + def EndNamespaceDeclHandler(self, prefix): self.out.append('End of NS decl: ' + repr(prefix)) - + def StartCdataSectionHandler(self): self.out.append('Start of CDATA section') - + def EndCdataSectionHandler(self): self.out.append('End of CDATA section') - + def CommentHandler(self, text): self.out.append('Comment: ' + repr(text)) - + def NotationDeclHandler(self, *args): name, base, sysid, pubid = args self.out.append('Notation declared: %s' %(args,)) - + def UnparsedEntityDeclHandler(self, *args): entityName, base, systemId, publicId, notationName = args self.out.append('Unparsed entity decl: %s' %(args,)) - + def NotStandaloneHandler(self, userData): self.out.append('Not standalone') return 1 - + def ExternalEntityRefHandler(self, *args): context, base, sysId, pubId = args self.out.append('External entity ref: %s' %(args[1:],)) return 1 - + def DefaultHandler(self, userData): pass - + def DefaultHandlerExpand(self, userData): pass @@ -129,7 +129,7 @@ #'NotStandaloneHandler', 'ExternalEntityRefHandler' ] - + def test_utf8(self): out = self.Outputter() @@ -138,7 +138,7 @@ setattr(parser, name, getattr(out, name)) parser.returns_unicode = 0 parser.Parse(data, 1) - + # Verify output op = out.out self.assertEquals(op[0], 'PI: \'xml-stylesheet\' \'href="stylesheet.css"\'') @@ -166,7 +166,7 @@ parser.returns_unicode = 1 for name in self.handler_names: setattr(parser, name, getattr(out, name)) - + parser.Parse(data, 1) op = out.out @@ -196,7 +196,7 @@ for name in self.handler_names: setattr(parser, name, getattr(out, name)) file = StringIO.StringIO(data) - + parser.ParseFile(file) op = out.out @@ -226,15 +226,15 @@ expat.ParserCreate() expat.ParserCreate(namespace_separator=None) expat.ParserCreate(namespace_separator=' ') - + def test_illegal(self): try: expat.ParserCreate(namespace_separator=42) self.fail() except TypeError, e: - self.assertEquals(str(e), + self.assertEquals(str(e), 'ParserCreate() argument 2 must be string or None, not int') - + try: expat.ParserCreate(namespace_separator='too long') self.fail() @@ -277,7 +277,7 @@ self.parser = expat.ParserCreate() self.parser.buffer_text = 1 self.parser.CharacterDataHandler = self.CharacterDataHandler - + def check(self, expected, label): self.assertEquals(self.stuff, expected, "%s\nstuff = %r\nexpected = %r" @@ -307,12 +307,12 @@ def test_default_to_disabled(self): parser = expat.ParserCreate() self.assertFalse(parser.buffer_text) - + def test_buffering_enabled(self): # Make sure buffering is turned on self.assertTrue(self.parser.buffer_text) self.parser.Parse("123", 1) - self.assertEquals(self.stuff, ['123'], + self.assertEquals(self.stuff, ['123'], "buffered text not properly collapsed") def test1(self): @@ -320,10 +320,10 @@ # XXX like, but it tests what we need to concisely. self.setHandlers(["StartElementHandler"]) self.parser.Parse("12\n34\n5", 1) - self.assertEquals(self.stuff, + self.assertEquals(self.stuff, ["", "1", "", "2", "\n", "3", "", "4\n5"], "buffering control not reacting as expected") - + def test2(self): self.parser.Parse("1<2> \n 3", 1) self.assertEquals(self.stuff, ["1<2> \n 3"], @@ -339,7 +339,7 @@ self.setHandlers(["StartElementHandler", "EndElementHandler"]) self.parser.CharacterDataHandler = None self.parser.Parse("123", 1) - self.assertEquals(self.stuff, + self.assertEquals(self.stuff, ["", "", "", "", "", ""]) def test5(self): @@ -349,11 +349,11 @@ ["", "1", "", "", "2", "", "", "3", ""]) def test6(self): - self.setHandlers(["CommentHandler", "EndElementHandler", + self.setHandlers(["CommentHandler", "EndElementHandler", "StartElementHandler"]) self.parser.Parse("12345 ", 1) - self.assertEquals(self.stuff, - ["", "1", "", "", "2", "", "", "345", ""], + self.assertEquals(self.stuff, + ["", "1", "", "", "2", "", "", "345", ""], "buffered text not properly split") def test7(self): @@ -399,7 +399,7 @@ self.assertTrue(self.upto < len(self.expected_list), 'too many parser events') expected = self.expected_list[self.upto] - self.assertEquals(pos, expected, + self.assertEquals(pos, expected, 'Expected position %s, got position %s' %(pos, expected)) self.upto += 1 @@ -422,16 +422,16 @@ xml = "%s" % ('a' * 1025) # this one doesn't crash #xml = "%s" % ('a' * 10000) - + class SpecificException(Exception): pass - + def handler(text): raise SpecificException - + parser = expat.ParserCreate() parser.CharacterDataHandler = handler - + self.assertRaises(Exception, parser.Parse, xml) Modified: python/trunk/Lib/test/test_re.py ============================================================================== --- python/trunk/Lib/test/test_re.py (original) +++ python/trunk/Lib/test/test_re.py Wed Apr 25 08:30:05 2007 @@ -607,7 +607,7 @@ for typecode in 'cbBuhHiIlLfd': a = array.array(typecode) self.assertEqual(re.compile("bla").match(a), None) - self.assertEqual(re.compile("").match(a).groups(), ()) + self.assertEqual(re.compile("").match(a).groups(), ()) def run_re_tests(): from test.re_tests import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR Modified: python/trunk/Lib/test/test_sax.py ============================================================================== --- python/trunk/Lib/test/test_sax.py (original) +++ python/trunk/Lib/test/test_sax.py Wed Apr 25 08:30:05 2007 @@ -36,7 +36,7 @@ self.assertEquals(attrs.get("attrs", 25), 25) self.assertEquals(attrs.items(), []) self.assertEquals(attrs.values(), []) - + def verify_empty_nsattrs(self, attrs): self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr")) self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr") @@ -70,7 +70,7 @@ self.assertEquals(attrs.getNameByQName("attr"), "attr") self.assertEquals(attrs["attr"], "val") self.assertEquals(attrs.getQNameByName("attr"), "attr") - + class MakeParserTest(unittest.TestCase): def test_make_parser2(self): # Creating parsers several times in a row should succeed. @@ -100,11 +100,11 @@ # ===== escape def test_escape_basic(self): self.assertEquals(escape("Donald Duck & Co"), "Donald Duck & Co") - + def test_escape_all(self): self.assertEquals(escape(""), "<Donald Duck & Co>") - + def test_escape_extra(self): self.assertEquals(escape("Hei p? deg", {"?" : "å"}), "Hei på deg") @@ -112,35 +112,35 @@ # ===== unescape def test_unescape_basic(self): self.assertEquals(unescape("Donald Duck & Co"), "Donald Duck & Co") - + def test_unescape_all(self): - self.assertEquals(unescape("<Donald Duck & Co>"), + self.assertEquals(unescape("<Donald Duck & Co>"), "") - + def test_unescape_extra(self): - self.assertEquals(unescape("Hei p? deg", {"?" : "å"}), + self.assertEquals(unescape("Hei p? deg", {"?" : "å"}), "Hei på deg") - + def test_unescape_amp_extra(self): self.assertEquals(unescape("&foo;", {"&foo;": "splat"}), "&foo;") # ===== quoteattr def test_quoteattr_basic(self): - self.assertEquals(quoteattr("Donald Duck & Co"), + self.assertEquals(quoteattr("Donald Duck & Co"), '"Donald Duck & Co"') - + def test_single_quoteattr(self): self.assertEquals(quoteattr('Includes "double" quotes'), '\'Includes "double" quotes\'') - + def test_double_quoteattr(self): self.assertEquals(quoteattr("Includes 'single' quotes"), "\"Includes 'single' quotes\"") - + def test_single_double_quoteattr(self): self.assertEquals(quoteattr("Includes 'single' and \"double\" quotes"), "\"Includes 'single' and "double" quotes\"") - + # ===== make_parser def test_make_parser(self): # Creating a parser should succeed - it should fall back @@ -160,19 +160,19 @@ gen.startElement("doc", {}) gen.endElement("doc") gen.endDocument() - + self.assertEquals(result.getvalue(), start + "") - + def test_xmlgen_content(self): result = StringIO() gen = XMLGenerator(result) - + gen.startDocument() gen.startElement("doc", {}) gen.characters("huhei") gen.endElement("doc") gen.endDocument() - + self.assertEquals(result.getvalue(), start + "huhei") def test_xmlgen_pi(self): @@ -197,7 +197,7 @@ gen.endElement("doc") gen.endDocument() - self.assertEquals(result.getvalue(), + self.assertEquals(result.getvalue(), start + "<huhei&") def test_xmlgen_attr_escape(self): @@ -215,7 +215,7 @@ gen.endElement("doc") gen.endDocument() - self.assertEquals(result.getvalue(), start + + self.assertEquals(result.getvalue(), start + ("" "" "")) @@ -285,7 +285,7 @@ gen.endPrefixMapping('my') gen.endDocument() - self.assertEquals(result.getvalue(), + self.assertEquals(result.getvalue(), start+'') @@ -314,7 +314,7 @@ xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read() class ExpatReaderTest(XmlTestBase): - + # ===== XMLReader support def test_expat_file(self): @@ -353,7 +353,7 @@ parser.feed('') parser.close() - self.assertEquals(handler._notations, + self.assertEquals(handler._notations, [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)]) self.assertEquals(handler._entities, [("img", None, "expat.gif", "GIF")]) @@ -378,7 +378,7 @@ parser.feed('&test;') parser.close() - self.assertEquals(result.getvalue(), start + + self.assertEquals(result.getvalue(), start + "") # ===== Attributes support @@ -433,7 +433,7 @@ self.assertEquals(attrs.getLength(), 1) self.assertEquals(attrs.getNames(), [(ns_uri, "attr")]) - self.assertTrue((attrs.getQNames() == [] or + self.assertTrue((attrs.getQNames() == [] or attrs.getQNames() == ["ns:attr"])) self.assertEquals(len(attrs), 1) self.assertTrue(attrs.has_key((ns_uri, "attr"))) @@ -445,101 +445,101 @@ self.assertEquals(attrs[(ns_uri, "attr")], "val") # ===== InputSource support - + def test_expat_inpsource_filename(self): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) - + parser.setContentHandler(xmlgen) parser.parse(findfile("test"+os.extsep+"xml")) self.assertEquals(result.getvalue(), xml_test_out) - + def test_expat_inpsource_sysid(self): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) - + parser.setContentHandler(xmlgen) parser.parse(InputSource(findfile("test"+os.extsep+"xml"))) self.assertEquals(result.getvalue(), xml_test_out) - + def test_expat_inpsource_stream(self): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) - + parser.setContentHandler(xmlgen) inpsrc = InputSource() inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml"))) parser.parse(inpsrc) - + self.assertEquals(result.getvalue(), xml_test_out) - + # ===== IncrementalParser support - + def test_expat_incremental(self): result = StringIO() xmlgen = XMLGenerator(result) parser = create_parser() parser.setContentHandler(xmlgen) - + parser.feed("") parser.feed("") parser.close() - + self.assertEquals(result.getvalue(), start + "") - + def test_expat_incremental_reset(self): result = StringIO() xmlgen = XMLGenerator(result) parser = create_parser() parser.setContentHandler(xmlgen) - + parser.feed("") parser.feed("text") - + result = StringIO() xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) parser.reset() - + parser.feed("") parser.feed("text") parser.feed("") parser.close() self.assertEquals(result.getvalue(), start + "text") - + # ===== Locator support - + def test_expat_locator_noinfo(self): result = StringIO() xmlgen = XMLGenerator(result) parser = create_parser() parser.setContentHandler(xmlgen) - + parser.feed("") parser.feed("") parser.close() - + self.assertEquals(parser.getSystemId(), None) self.assertEquals(parser.getPublicId(), None) self.assertEquals(parser.getLineNumber(), 1) - + def test_expat_locator_withinfo(self): result = StringIO() xmlgen = XMLGenerator(result) parser = create_parser() parser.setContentHandler(xmlgen) parser.parse(findfile("test.xml")) - + self.assertEquals(parser.getSystemId(), findfile("test.xml")) self.assertEquals(parser.getPublicId(), None) - - + + # =========================================================================== # # error reporting @@ -559,12 +559,12 @@ self.fail() except SAXException, e: self.assertEquals(e.getSystemId(), name) - + def test_expat_incomplete(self): parser = create_parser() parser.setContentHandler(ContentHandler()) # do nothing self.assertRaises(SAXParseException, parser.parse, StringIO("")) - + def test_sax_parse_exception_str(self): # pass various values from a locator to the SAXParseException to # make sure that the __str__() doesn't fall apart when None is @@ -582,21 +582,21 @@ # use None for both: str(SAXParseException("message", None, self.DummyLocator(None, None))) - + class DummyLocator: def __init__(self, lineno, colno): self._lineno = lineno self._colno = colno - + def getPublicId(self): return "pubid" - + def getSystemId(self): return "sysid" - + def getLineNumber(self): return self._lineno - + def getColumnNumber(self): return self._colno @@ -607,21 +607,21 @@ # =========================================================================== class XmlReaderTest(XmlTestBase): - + # ===== AttributesImpl def test_attrs_empty(self): self.verify_empty_attrs(AttributesImpl({})) - + def test_attrs_wattr(self): self.verify_attrs_wattr(AttributesImpl({"attr" : "val"})) - + def test_nsattrs_empty(self): self.verify_empty_nsattrs(AttributesNSImpl({}, {})) - + def test_nsattrs_wattr(self): attrs = AttributesNSImpl({(ns_uri, "attr") : "val"}, {(ns_uri, "attr") : "ns:attr"}) - + self.assertEquals(attrs.getLength(), 1) self.assertEquals(attrs.getNames(), [(ns_uri, "attr")]) self.assertEquals(attrs.getQNames(), ["ns:attr"]) @@ -661,7 +661,7 @@ # attempt. Keeping these tests around will help detect problems with # other attempts to provide reliable access to the standard library's # implementation of the XML support. - + def test_sf_1511497(self): # Bug report: http://www.python.org/sf/1511497 import sys @@ -675,7 +675,7 @@ self.assertEquals(module.__name__, "xml.sax.expatreader") finally: sys.modules.update(old_modules) - + def test_sf_1513611(self): # Bug report: http://www.python.org/sf/1513611 sio = StringIO("invalid") @@ -693,4 +693,4 @@ XmlReaderTest) if __name__ == "__main__": - unittest_main() + unittest_main() Modified: python/trunk/Lib/test/test_set.py ============================================================================== --- python/trunk/Lib/test/test_set.py (original) +++ python/trunk/Lib/test/test_set.py Wed Apr 25 08:30:05 2007 @@ -288,7 +288,7 @@ self.assertEqual(sum(elem.hash_count for elem in d), n) if hasattr(s, 'symmetric_difference_update'): s.symmetric_difference_update(d) - self.assertEqual(sum(elem.hash_count for elem in d), n) + self.assertEqual(sum(elem.hash_count for elem in d), n) d2 = dict.fromkeys(set(d)) self.assertEqual(sum(elem.hash_count for elem in d), n) d3 = dict.fromkeys(frozenset(d)) Modified: python/trunk/Lib/test/test_smtplib.py ============================================================================== --- python/trunk/Lib/test/test_smtplib.py (original) +++ python/trunk/Lib/test/test_smtplib.py Wed Apr 25 08:30:05 2007 @@ -25,7 +25,7 @@ evt.set() class GeneralTests(TestCase): - + def setUp(self): self.evt = threading.Event() threading.Thread(target=server, args=(self.evt,)).start() @@ -38,13 +38,13 @@ # connects smtp = smtplib.SMTP("localhost", 9091) smtp.sock.close() - + def testTimeoutDefault(self): # default smtp = smtplib.SMTP("localhost", 9091) self.assertTrue(smtp.sock.gettimeout() is None) smtp.sock.close() - + def testTimeoutValue(self): # a value smtp = smtplib.SMTP("localhost", 9091, timeout=30) Modified: python/trunk/Lib/test/test_socket.py ============================================================================== --- python/trunk/Lib/test/test_socket.py (original) +++ python/trunk/Lib/test/test_socket.py Wed Apr 25 08:30:05 2007 @@ -822,7 +822,7 @@ def clientSetUp(self): self.cli = socket.create_connection((HOST, PORT)) self.serv_conn = self.cli - + class BasicTCPTest2(NetworkConnectionTest, BasicTCPTest): """Tests that NetworkConnection does not break existing TCP functionality. """ @@ -853,22 +853,22 @@ self.cli = socket.create_connection((HOST, PORT), timeout=30) self.assertEqual(self.cli.family, 2) - testTimeoutDefault = _justAccept + testTimeoutDefault = _justAccept def _testTimeoutDefault(self): self.cli = socket.create_connection((HOST, PORT)) self.assertTrue(self.cli.gettimeout() is None) - - testTimeoutValueNamed = _justAccept + + testTimeoutValueNamed = _justAccept def _testTimeoutValueNamed(self): self.cli = socket.create_connection((HOST, PORT), timeout=30) self.assertEqual(self.cli.gettimeout(), 30) - testTimeoutValueNonamed = _justAccept + testTimeoutValueNonamed = _justAccept def _testTimeoutValueNonamed(self): self.cli = socket.create_connection((HOST, PORT), 30) self.assertEqual(self.cli.gettimeout(), 30) - testTimeoutNone = _justAccept + testTimeoutNone = _justAccept def _testTimeoutNone(self): previous = socket.getdefaulttimeout() socket.setdefaulttimeout(30) Modified: python/trunk/Lib/test/test_socket_ssl.py ============================================================================== --- python/trunk/Lib/test/test_socket_ssl.py (original) +++ python/trunk/Lib/test/test_socket_ssl.py Wed Apr 25 08:30:05 2007 @@ -25,12 +25,12 @@ else: print "didn't raise TypeError" socket.RAND_add("this is a random string", 75.0) - + with test_support.transient_internet(): f = urllib.urlopen('https://sf.net') buf = f.read() f.close() - + def testTimeout(self): def error_msg(extra_msg): print >> sys.stderr, """\ @@ -38,14 +38,14 @@ test_timeout. That may be legitimate, but is not the outcome we hoped for. If this message is seen often, test_timeout should be changed to use a more reliable address.""" % (ADDR, extra_msg) - + # A service which issues a welcome banner (without need to write # anything). # XXX ("gmail.org", 995) has been unreliable so far, from time to - # XXX time non-responsive for hours on end (& across all buildbot + # XXX time non-responsive for hours on end (& across all buildbot # XXX slaves, so that's not just a local thing). ADDR = "gmail.org", 995 - + s = socket.socket() s.settimeout(30.0) try: @@ -59,7 +59,7 @@ return else: raise - + ss = socket.ssl(s) # Read part of return welcome banner twice. ss.read(1) @@ -71,11 +71,11 @@ def testRudeShutdown(self): # Some random port to connect to. PORT = [9934] - + listener_ready = threading.Event() listener_gone = threading.Event() - - # `listener` runs in a thread. It opens a socket listening on + + # `listener` runs in a thread. It opens a socket listening on # PORT, and sits in an accept() until the main thread connects. # Then it rudely closes the socket, and sets Event `listener_gone` # to let the main thread know the socket is gone. @@ -87,7 +87,7 @@ s.accept() s = None # reclaim the socket object, which also closes it listener_gone.set() - + def connector(): listener_ready.wait() s = socket.socket() @@ -100,7 +100,7 @@ else: raise test_support.TestFailed( 'connecting to closed SSL socket should have failed') - + t = threading.Thread(target=listener) t.start() connector() @@ -153,8 +153,8 @@ try: cmd = "openssl s_server -cert %s -key %s -quiet" % (cert_file, key_file) - self.s = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, - stdout=subprocess.PIPE, + self.s = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) time.sleep(1) except: @@ -171,7 +171,7 @@ self.haveServer = False else: self.haveServer = True - + def run(self): while self.keepServing: time.sleep(.5) @@ -186,7 +186,7 @@ subprocess.TerminateProcess(int(self.s._handle), -1) else: os.kill(self.s.pid, 15) - + def test_main(): if not hasattr(socket, "ssl"): raise test_support.TestSkipped("socket module has no ssl support") Modified: python/trunk/Lib/test/test_softspace.py ============================================================================== --- python/trunk/Lib/test/test_softspace.py (original) +++ python/trunk/Lib/test/test_softspace.py Wed Apr 25 08:30:05 2007 @@ -15,9 +15,9 @@ print >> f, 'f', 'g' # In 2.2 & earlier, this printed ' a\nbc d\te\nf g\n' self.assertEqual(f.getvalue(), 'a\nb c d\te\nf g\n') - + def test_main(): run_unittest(SoftspaceTests) - + if __name__ == '__main__': test_main() Modified: python/trunk/Lib/test/test_stringprep.py ============================================================================== --- python/trunk/Lib/test/test_stringprep.py (original) +++ python/trunk/Lib/test/test_stringprep.py Wed Apr 25 08:30:05 2007 @@ -91,6 +91,6 @@ def test_main(): test_support.run_unittest(StringprepTests) - + if __name__ == '__main__': test_main() Modified: python/trunk/Lib/test/test_syntax.py ============================================================================== --- python/trunk/Lib/test/test_syntax.py (original) +++ python/trunk/Lib/test/test_syntax.py Wed Apr 25 08:30:05 2007 @@ -376,7 +376,7 @@ ... elif 1: ... pass Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 2) >>> if 1: @@ -384,7 +384,7 @@ ... elif 1: ... x() = 1 Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 4) >>> if 1: @@ -394,7 +394,7 @@ ... else: ... pass Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 2) >>> if 1: @@ -404,7 +404,7 @@ ... else: ... pass Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 4) >>> if 1: @@ -414,7 +414,7 @@ ... else: ... x() = 1 Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 6) """ Modified: python/trunk/Lib/test/test_tarfile.py ============================================================================== --- python/trunk/Lib/test/test_tarfile.py (original) +++ python/trunk/Lib/test/test_tarfile.py Wed Apr 25 08:30:05 2007 @@ -987,4 +987,3 @@ if __name__ == "__main__": test_main() - Modified: python/trunk/Lib/test/test_telnetlib.py ============================================================================== --- python/trunk/Lib/test/test_telnetlib.py (original) +++ python/trunk/Lib/test/test_telnetlib.py Wed Apr 25 08:30:05 2007 @@ -22,7 +22,7 @@ evt.set() class GeneralTests(TestCase): - + def setUp(self): self.evt = threading.Event() threading.Thread(target=server, args=(self.evt,)).start() @@ -35,13 +35,13 @@ # connects telnet = telnetlib.Telnet("localhost", 9091) telnet.sock.close() - + def testTimeoutDefault(self): # default telnet = telnetlib.Telnet("localhost", 9091) self.assertTrue(telnet.sock.gettimeout() is None) telnet.sock.close() - + def testTimeoutValue(self): # a value telnet = telnetlib.Telnet("localhost", 9091, timeout=30) Modified: python/trunk/Lib/test/test_zipfile.py ============================================================================== --- python/trunk/Lib/test/test_zipfile.py (original) +++ python/trunk/Lib/test/test_zipfile.py Wed Apr 25 08:30:05 2007 @@ -514,7 +514,7 @@ # version of .testzip would swallow this exception (and any other) # and report that the first file in the archive was corrupt. self.assertRaises(RuntimeError, zipf.testzip) - + def tearDown(self): support.unlink(TESTFN) support.unlink(TESTFN2) @@ -568,7 +568,7 @@ fp = open(TESTFN, "wb") fp.write(self.data) fp.close() - + def tearDown(self): support.unlink(TESTFN) support.unlink(TESTFN2) Modified: python/trunk/Lib/timeit.py ============================================================================== --- python/trunk/Lib/timeit.py (original) +++ python/trunk/Lib/timeit.py Wed Apr 25 08:30:05 2007 @@ -223,13 +223,13 @@ def timeit(stmt="pass", setup="pass", timer=default_timer, number=default_number): - """Convenience function to create Timer object and call timeit method.""" - return Timer(stmt, setup, timer).timeit(number) + """Convenience function to create Timer object and call timeit method.""" + return Timer(stmt, setup, timer).timeit(number) def repeat(stmt="pass", setup="pass", timer=default_timer, repeat=default_repeat, number=default_number): - """Convenience function to create Timer object and call repeat method.""" - return Timer(stmt, setup, timer).repeat(repeat, number) + """Convenience function to create Timer object and call repeat method.""" + return Timer(stmt, setup, timer).repeat(repeat, number) def main(args=None): """Main program, used when run as a script. Modified: python/trunk/Lib/urllib2.py ============================================================================== --- python/trunk/Lib/urllib2.py (original) +++ python/trunk/Lib/urllib2.py Wed Apr 25 08:30:05 2007 @@ -490,7 +490,7 @@ def http_response(self, request, response): code, msg, hdrs = response.code, response.msg, response.info() - # According to RFC 2616, "2xx" code indicates that the client's + # According to RFC 2616, "2xx" code indicates that the client's # request was successfully received, understood, and accepted. if not (200 <= code < 300): response = self.parent.error( From python-checkins at python.org Wed Apr 25 08:42:55 2007 From: python-checkins at python.org (neal.norwitz) Date: Wed, 25 Apr 2007 08:42:55 +0200 (CEST) Subject: [Python-checkins] r54954 - in python/branches/release25-maint/Lib: CGIHTTPServer.py distutils/unixccompiler.py ftplib.py lib-tk/tkSimpleDialog.py subprocess.py test/test_codecs.py test/test_curses.py test/test_descr.py test/test_import.py test/test_mailbox.py test/test_old_mailbox.py test/test_re.py test/test_sax.py test/test_set.py test/test_syntax.py Message-ID: <20070425064255.3721A1E400C@bag.python.org> Author: neal.norwitz Date: Wed Apr 25 08:42:41 2007 New Revision: 54954 Modified: python/branches/release25-maint/Lib/CGIHTTPServer.py python/branches/release25-maint/Lib/distutils/unixccompiler.py python/branches/release25-maint/Lib/ftplib.py python/branches/release25-maint/Lib/lib-tk/tkSimpleDialog.py python/branches/release25-maint/Lib/subprocess.py python/branches/release25-maint/Lib/test/test_codecs.py python/branches/release25-maint/Lib/test/test_curses.py python/branches/release25-maint/Lib/test/test_descr.py python/branches/release25-maint/Lib/test/test_import.py python/branches/release25-maint/Lib/test/test_mailbox.py python/branches/release25-maint/Lib/test/test_old_mailbox.py python/branches/release25-maint/Lib/test/test_re.py python/branches/release25-maint/Lib/test/test_sax.py python/branches/release25-maint/Lib/test/test_set.py python/branches/release25-maint/Lib/test/test_syntax.py Log: Whitespace normalization Modified: python/branches/release25-maint/Lib/CGIHTTPServer.py ============================================================================== --- python/branches/release25-maint/Lib/CGIHTTPServer.py (original) +++ python/branches/release25-maint/Lib/CGIHTTPServer.py Wed Apr 25 08:42:41 2007 @@ -107,7 +107,7 @@ """Execute a CGI script.""" path = self.path dir, rest = self.cgi_info - + i = path.find('/', len(dir) + 1) while i >= 0: nextdir = path[:i] Modified: python/branches/release25-maint/Lib/distutils/unixccompiler.py ============================================================================== --- python/branches/release25-maint/Lib/distutils/unixccompiler.py (original) +++ python/branches/release25-maint/Lib/distutils/unixccompiler.py Wed Apr 25 08:42:41 2007 @@ -82,7 +82,7 @@ except ValueError: pass - # Check if the SDK that is used during compilation actually exists, + # Check if the SDK that is used during compilation actually exists, # the universal build requires the usage of a universal SDK and not all # users have that installed by default. sysroot = None Modified: python/branches/release25-maint/Lib/ftplib.py ============================================================================== --- python/branches/release25-maint/Lib/ftplib.py (original) +++ python/branches/release25-maint/Lib/ftplib.py Wed Apr 25 08:42:41 2007 @@ -332,7 +332,7 @@ # 1xx or error messages for LIST), so we just discard # this response. if resp[0] == '2': - resp = self.getresp() + resp = self.getresp() if resp[0] != '1': raise error_reply, resp else: @@ -342,7 +342,7 @@ resp = self.sendcmd(cmd) # See above. if resp[0] == '2': - resp = self.getresp() + resp = self.getresp() if resp[0] != '1': raise error_reply, resp conn, sockaddr = sock.accept() Modified: python/branches/release25-maint/Lib/lib-tk/tkSimpleDialog.py ============================================================================== --- python/branches/release25-maint/Lib/lib-tk/tkSimpleDialog.py (original) +++ python/branches/release25-maint/Lib/lib-tk/tkSimpleDialog.py Wed Apr 25 08:42:41 2007 @@ -50,9 +50,9 @@ # If the master is not viewable, don't # make the child transient, or else it # would be opened withdrawn - if parent.winfo_viewable(): + if parent.winfo_viewable(): self.transient(parent) - + if title: self.title(title) Modified: python/branches/release25-maint/Lib/subprocess.py ============================================================================== --- python/branches/release25-maint/Lib/subprocess.py (original) +++ python/branches/release25-maint/Lib/subprocess.py Wed Apr 25 08:42:41 2007 @@ -596,7 +596,7 @@ # either have to redirect all three or none. If the subprocess # user has only redirected one or two handles, we are # automatically creating PIPEs for the rest. We should close - # these after the process is started. See bug #1124861. + # these after the process is started. See bug #1124861. if mswindows: if stdin is None and p2cwrite is not None: os.close(p2cwrite) @@ -1142,7 +1142,7 @@ # we can write up to PIPE_BUF bytes without risk # blocking. POSIX defines PIPE_BUF >= 512 bytes_written = os.write(self.stdin.fileno(), buffer(input, input_offset, 512)) - input_offset += bytes_written + input_offset += bytes_written if input_offset >= len(input): self.stdin.close() write_set.remove(self.stdin) Modified: python/branches/release25-maint/Lib/test/test_codecs.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_codecs.py (original) +++ python/branches/release25-maint/Lib/test/test_codecs.py Wed Apr 25 08:42:41 2007 @@ -921,7 +921,7 @@ self.assertEquals(f.readlines(), [u'\ud55c\n', u'\uae00']) class EncodedFileTest(unittest.TestCase): - + def test_basic(self): f = StringIO.StringIO('\xed\x95\x9c\n\xea\xb8\x80') ef = codecs.EncodedFile(f, 'utf-16-le', 'utf-8') Modified: python/branches/release25-maint/Lib/test/test_curses.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_curses.py (original) +++ python/branches/release25-maint/Lib/test/test_curses.py Wed Apr 25 08:42:41 2007 @@ -245,7 +245,7 @@ if hasattr(curses, 'resizeterm'): lines, cols = curses.LINES, curses.COLS curses.resizeterm(lines - 1, cols + 1) - + if curses.LINES != lines - 1 or curses.COLS != cols + 1: raise RuntimeError, "Expected resizeterm to update LINES and COLS" Modified: python/branches/release25-maint/Lib/test/test_descr.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_descr.py (original) +++ python/branches/release25-maint/Lib/test/test_descr.py Wed Apr 25 08:42:41 2007 @@ -1216,7 +1216,7 @@ except NameError: pass else: - # _unicode_to_string used to modify slots in certain circumstances + # _unicode_to_string used to modify slots in certain circumstances slots = (unicode("foo"), unicode("bar")) class C(object): __slots__ = slots @@ -1231,7 +1231,7 @@ except (TypeError, UnicodeEncodeError): pass else: - raise TestFailed, "[unichr(128)] slots not caught" + raise TestFailed, "[unichr(128)] slots not caught" # Test leaks class Counted(object): Modified: python/branches/release25-maint/Lib/test/test_import.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_import.py (original) +++ python/branches/release25-maint/Lib/test/test_import.py Wed Apr 25 08:42:41 2007 @@ -224,13 +224,13 @@ test_import_initless_directory_warning() def test_infinite_reload(): - # Bug #742342 reports that Python segfaults (infinite recursion in C) - # when faced with self-recursive reload()ing. + # Bug #742342 reports that Python segfaults (infinite recursion in C) + # when faced with self-recursive reload()ing. - sys.path.insert(0, os.path.dirname(__file__)) - try: - import infinite_reload - finally: - sys.path.pop(0) + sys.path.insert(0, os.path.dirname(__file__)) + try: + import infinite_reload + finally: + sys.path.pop(0) test_infinite_reload() Modified: python/branches/release25-maint/Lib/test/test_mailbox.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_mailbox.py (original) +++ python/branches/release25-maint/Lib/test/test_mailbox.py Wed Apr 25 08:42:41 2007 @@ -681,11 +681,11 @@ box = self._factory(self._path, factory=dummy_factory) folder = box.add_folder('folder1') self.assert_(folder._factory is dummy_factory) - + folder1_alias = box.get_folder('folder1') self.assert_(folder1_alias._factory is dummy_factory) - + class _TestMboxMMDF(TestMailbox): @@ -767,15 +767,15 @@ key1 = self._box.add(msg) self._box.flush() self._box.close() - + self._box = self._factory(self._path) self._box.lock() key2 = self._box.add(msg) self._box.flush() self.assert_(self._box._locked) self._box.close() - - + + class TestMbox(_TestMboxMMDF): @@ -805,7 +805,7 @@ def dummy_factory (s): return None self._box = self._factory(self._path, dummy_factory) - + new_folder = self._box.add_folder('foo.bar') folder0 = self._box.get_folder('foo.bar') folder0.add(self._template % 'bar') @@ -901,7 +901,7 @@ self.assert_(self._box.get_sequences() == {'foo':[1, 2, 3, 4, 5], 'unseen':[1], 'bar':[3], 'replied':[3]}) - + def _get_lock_path(self): return os.path.join(self._path, '.mh_sequences.lock') Modified: python/branches/release25-maint/Lib/test/test_old_mailbox.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_old_mailbox.py (original) +++ python/branches/release25-maint/Lib/test/test_old_mailbox.py Wed Apr 25 08:42:41 2007 @@ -116,7 +116,7 @@ def tearDown(self): os.unlink(self._path) - + def test_from_regex (self): # Testing new regex from bug #1633678 f = open(self._path, 'w') Modified: python/branches/release25-maint/Lib/test/test_re.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_re.py (original) +++ python/branches/release25-maint/Lib/test/test_re.py Wed Apr 25 08:42:41 2007 @@ -610,7 +610,7 @@ for typecode in 'cbBuhHiIlLfd': a = array.array(typecode) self.assertEqual(re.compile("bla").match(a), None) - self.assertEqual(re.compile("").match(a).groups(), ()) + self.assertEqual(re.compile("").match(a).groups(), ()) def run_re_tests(): from test.re_tests import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR Modified: python/branches/release25-maint/Lib/test/test_sax.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_sax.py (original) +++ python/branches/release25-maint/Lib/test/test_sax.py Wed Apr 25 08:42:41 2007 @@ -252,7 +252,7 @@ gen.endDocument() return result.getvalue() == start+'' - + # ===== Xmlfilterbase def test_filter_basic(): Modified: python/branches/release25-maint/Lib/test/test_set.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_set.py (original) +++ python/branches/release25-maint/Lib/test/test_set.py Wed Apr 25 08:42:41 2007 @@ -288,7 +288,7 @@ self.assertEqual(sum(elem.hash_count for elem in d), n) if hasattr(s, 'symmetric_difference_update'): s.symmetric_difference_update(d) - self.assertEqual(sum(elem.hash_count for elem in d), n) + self.assertEqual(sum(elem.hash_count for elem in d), n) d2 = dict.fromkeys(set(d)) self.assertEqual(sum(elem.hash_count for elem in d), n) d3 = dict.fromkeys(frozenset(d)) @@ -500,7 +500,7 @@ set.__init__(self, iterable) class TestSetSubclassWithKeywordArgs(TestSet): - + def test_keywords_in_subclass(self): 'SF bug #1486663 -- this used to erroneously raise a TypeError' SetSubclassWithKeywordArgs(newarg=1) @@ -1487,7 +1487,7 @@ test_classes = ( TestSet, TestSetSubclass, - TestSetSubclassWithKeywordArgs, + TestSetSubclassWithKeywordArgs, TestFrozenSet, TestFrozenSetSubclass, TestSetOfSets, Modified: python/branches/release25-maint/Lib/test/test_syntax.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_syntax.py (original) +++ python/branches/release25-maint/Lib/test/test_syntax.py Wed Apr 25 08:42:41 2007 @@ -373,7 +373,7 @@ ... elif 1: ... pass Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 2) >>> if 1: @@ -381,7 +381,7 @@ ... elif 1: ... x() = 1 Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 4) >>> if 1: @@ -391,7 +391,7 @@ ... else: ... pass Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 2) >>> if 1: @@ -401,7 +401,7 @@ ... else: ... pass Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 4) >>> if 1: @@ -411,7 +411,7 @@ ... else: ... x() = 1 Traceback (most recent call last): - ... + ... SyntaxError: can't assign to function call (, line 6) """ From buildbot at python.org Wed Apr 25 08:58:50 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 06:58:50 +0000 Subject: [Python-checkins] buildbot warnings in x86 XP trunk Message-ID: <20070425065851.822EE1E400B@bag.python.org> The Buildbot has detected a new failure of x86 XP trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520XP%2520trunk/builds/395 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl,neal.norwitz Build had warnings: warnings failed slave lost sincerely, -The Buildbot From python-checkins at python.org Wed Apr 25 17:19:10 2007 From: python-checkins at python.org (david.goodger) Date: Wed, 25 Apr 2007 17:19:10 +0200 (CEST) Subject: [Python-checkins] r54955 - peps/trunk/pep-3119.txt Message-ID: <20070425151910.A20471E400B@bag.python.org> Author: david.goodger Date: Wed Apr 25 17:19:08 2007 New Revision: 54955 Modified: peps/trunk/pep-3119.txt Log: markup fix Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Wed Apr 25 17:19:08 2007 @@ -158,7 +158,7 @@ The ``type.__new__`` method computes the type attribute ``__abstractmethods__`` as the set of all method names that have an ``__isabstractmethod__`` attribute whose value is true. It does this -by combining the ``__abstractmethods__` attributes of the base +by combining the ``__abstractmethods__`` attributes of the base classes, adding the names of all methods in the new class dict that have a true ``__isabstractmethod__`` attribute, and removing the names of all methods in the new class dict that don't have a true From python-checkins at python.org Wed Apr 25 19:29:57 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 25 Apr 2007 19:29:57 +0200 (CEST) Subject: [Python-checkins] r54956 - in python/trunk: Doc/lib/libtest.tex Lib/test/README Lib/test/test_base64.py Lib/test/test_bsddb3.py Lib/test/test_codecencodings_cn.py Lib/test/test_codecencodings_hk.py Lib/test/test_codecencodings_jp.py Lib/test/test_codecencodings_kr.py Lib/test/test_codecencodings_tw.py Lib/test/test_codecmaps_cn.py Lib/test/test_codecmaps_hk.py Lib/test/test_codecmaps_jp.py Lib/test/test_codecmaps_kr.py Lib/test/test_codecmaps_tw.py Lib/test/test_contextlib.py Lib/test/test_ctypes.py Lib/test/test_datetime.py Lib/test/test_email.py Lib/test/test_email_codecs.py Lib/test/test_email_renamed.py Lib/test/test_gettext.py Lib/test/test_multibytecodec.py Lib/test/test_optparse.py Lib/test/test_robotparser.py Lib/test/test_support.py Lib/test/test_threading_local.py Lib/test/test_unicode.py Lib/test/test_unicode_file.py Lib/test/test_wsgiref.py Message-ID: <20070425172957.7177C1E400C@bag.python.org> Author: collin.winter Date: Wed Apr 25 19:29:52 2007 New Revision: 54956 Modified: python/trunk/Doc/lib/libtest.tex python/trunk/Lib/test/README python/trunk/Lib/test/test_base64.py python/trunk/Lib/test/test_bsddb3.py python/trunk/Lib/test/test_codecencodings_cn.py python/trunk/Lib/test/test_codecencodings_hk.py python/trunk/Lib/test/test_codecencodings_jp.py python/trunk/Lib/test/test_codecencodings_kr.py python/trunk/Lib/test/test_codecencodings_tw.py python/trunk/Lib/test/test_codecmaps_cn.py python/trunk/Lib/test/test_codecmaps_hk.py python/trunk/Lib/test/test_codecmaps_jp.py python/trunk/Lib/test/test_codecmaps_kr.py python/trunk/Lib/test/test_codecmaps_tw.py python/trunk/Lib/test/test_contextlib.py python/trunk/Lib/test/test_ctypes.py python/trunk/Lib/test/test_datetime.py python/trunk/Lib/test/test_email.py python/trunk/Lib/test/test_email_codecs.py python/trunk/Lib/test/test_email_renamed.py python/trunk/Lib/test/test_gettext.py python/trunk/Lib/test/test_multibytecodec.py python/trunk/Lib/test/test_optparse.py python/trunk/Lib/test/test_robotparser.py python/trunk/Lib/test/test_support.py python/trunk/Lib/test/test_threading_local.py python/trunk/Lib/test/test_unicode.py python/trunk/Lib/test/test_unicode_file.py python/trunk/Lib/test/test_wsgiref.py Log: Standardize on test.test_support.run_unittest() (as opposed to a mix of run_unittest() and run_suite()). Also, add functionality to run_unittest() that admits usage of unittest.TestLoader.loadTestsFromModule(). Modified: python/trunk/Doc/lib/libtest.tex ============================================================================== --- python/trunk/Doc/lib/libtest.tex (original) +++ python/trunk/Doc/lib/libtest.tex Wed Apr 25 19:29:52 2007 @@ -196,7 +196,9 @@ This module defines the following exceptions: \begin{excdesc}{TestFailed} -Exception to be raised when a test fails. +Exception to be raised when a test fails. This is deprecated in favor +of \module{unittest}-based tests and \class{unittest.TestCase}'s +assertion methods. \end{excdesc} \begin{excdesc}{TestSkipped} @@ -273,14 +275,18 @@ Execute \class{unittest.TestCase} subclasses passed to the function. The function scans the classes for methods starting with the prefix \samp{test_} and executes the tests individually. -This is the preferred way to execute tests. -\end{funcdesc} -\begin{funcdesc}{run_suite}{suite\optional{, testclass}} -Execute the \class{unittest.TestSuite} instance \var{suite}. -The optional argument \var{testclass} accepts one of the test classes in the -suite so as to print out more detailed information on where the testing suite -originated from. +It is also legal to pass strings as parameters; these should be keys in +\code{sys.modules}. Each associated module will be scanned by +\code{unittest.TestLoader.loadTestsFromModule()}. This is usually seen in +the following \function{test_main()} function: + +\begin{verbatim} +def test_main(): + test_support.run_unittest(__name__) +\end{verbatim} + +This will run all tests defined in the named module. \end{funcdesc} The \module{test.test_support} module defines the following classes: Modified: python/trunk/Lib/test/README ============================================================================== --- python/trunk/Lib/test/README (original) +++ python/trunk/Lib/test/README Wed Apr 25 19:29:52 2007 @@ -40,18 +40,22 @@ see the documentation of the unittest_ module for detailed information on the interface and general guidelines on writing unittest-based tests. -The test_support helper module provides two functions for use by -unittest-based tests in the Python regression testing framework: - -- ``run_unittest()`` takes a number of ``unittest.TestCase`` derived classes as - parameters and runs the tests defined in those classes. - -- ``run_suite()`` takes a populated ``TestSuite`` instance and runs the - tests. +The test_support helper module provides a function for use by +unittest-based tests in the Python regression testing framework, +``run_unittest()``. This is the primary way of running tests in the +standard library. You can pass it any number of the following: + +- classes derived from or instances of ``unittest.TestCase`` or + ``unittest.TestSuite``. These will be handed off to unittest for + converting into a proper TestSuite instance. + +- a string; this must be a key in sys.modules. The module associated with + that string will be scanned by ``unittest.TestLoader.loadTestsFromModule``. + This is usually seen as ``test_support.run_unittest(__name__)`` in a test + module's ``test_main()`` function. This has the advantage of picking up + new tests automatically, without you having to add each new test case + manually. -``run_suite()`` is preferred because unittest files typically grow multiple -test classes, and you might as well be prepared. - All test methods in the Python regression framework have names that start with "``test_``" and use lower-case names with words separated with underscores. @@ -96,11 +100,7 @@ ...etc... def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(MyTestCase1)) - suite.addTest(unittest.makeSuite(MyTestCase2)) - ...add more suites... - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_base64.py ============================================================================== --- python/trunk/Lib/test/test_base64.py (original) +++ python/trunk/Lib/test/test_base64.py Wed Apr 25 19:29:52 2007 @@ -183,16 +183,8 @@ -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(LegacyBase64TestCase)) - suite.addTest(unittest.makeSuite(BaseXYTestCase)) - return suite - - def test_main(): - test_support.run_suite(suite()) - + test_support.run_unittest(__name__) if __name__ == '__main__': - unittest.main(defaultTest='suite') + test_main() Modified: python/trunk/Lib/test/test_bsddb3.py ============================================================================== --- python/trunk/Lib/test/test_bsddb3.py (original) +++ python/trunk/Lib/test/test_bsddb3.py Wed Apr 25 19:29:52 2007 @@ -4,11 +4,11 @@ """ import sys import unittest -from test.test_support import requires, verbose, run_suite, unlink +from test.test_support import requires, verbose, run_unittest, unlink # When running as a script instead of within the regrtest framework, skip the # requires test, since it's obvious we want to run them. -if __name__ <> '__main__': +if __name__ != '__main__': requires('bsddb') verbose = False @@ -58,9 +58,7 @@ # For invocation through regrtest def test_main(): - tests = suite() - run_suite(tests) - + run_unittest(suite()) # For invocation as a script if __name__ == '__main__': @@ -73,4 +71,4 @@ print 'python version: %s' % sys.version print '-=' * 38 - unittest.main(defaultTest='suite') + test_main() Modified: python/trunk/Lib/test/test_codecencodings_cn.py ============================================================================== --- python/trunk/Lib/test/test_codecencodings_cn.py (original) +++ python/trunk/Lib/test/test_codecencodings_cn.py Wed Apr 25 19:29:52 2007 @@ -51,11 +51,7 @@ has_iso10646 = True def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_GB2312)) - suite.addTest(unittest.makeSuite(Test_GBK)) - suite.addTest(unittest.makeSuite(Test_GB18030)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_codecencodings_hk.py ============================================================================== --- python/trunk/Lib/test/test_codecencodings_hk.py (original) +++ python/trunk/Lib/test/test_codecencodings_hk.py Wed Apr 25 19:29:52 2007 @@ -21,9 +21,7 @@ ) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_Big5HKSCS)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_codecencodings_jp.py ============================================================================== --- python/trunk/Lib/test/test_codecencodings_jp.py (original) +++ python/trunk/Lib/test/test_codecencodings_jp.py Wed Apr 25 19:29:52 2007 @@ -99,13 +99,7 @@ ) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_CP932)) - suite.addTest(unittest.makeSuite(Test_EUC_JISX0213)) - suite.addTest(unittest.makeSuite(Test_EUC_JP_COMPAT)) - suite.addTest(unittest.makeSuite(Test_SJIS_COMPAT)) - suite.addTest(unittest.makeSuite(Test_SJISX0213)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_codecencodings_kr.py ============================================================================== --- python/trunk/Lib/test/test_codecencodings_kr.py (original) +++ python/trunk/Lib/test/test_codecencodings_kr.py Wed Apr 25 19:29:52 2007 @@ -45,11 +45,7 @@ ) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_CP949)) - suite.addTest(unittest.makeSuite(Test_EUCKR)) - suite.addTest(unittest.makeSuite(Test_JOHAB)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_codecencodings_tw.py ============================================================================== --- python/trunk/Lib/test/test_codecencodings_tw.py (original) +++ python/trunk/Lib/test/test_codecencodings_tw.py Wed Apr 25 19:29:52 2007 @@ -21,9 +21,7 @@ ) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_Big5)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_codecmaps_cn.py ============================================================================== --- python/trunk/Lib/test/test_codecmaps_cn.py (original) +++ python/trunk/Lib/test/test_codecmaps_cn.py Wed Apr 25 19:29:52 2007 @@ -20,10 +20,7 @@ 'MICSFT/WINDOWS/CP936.TXT' def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestGB2312Map)) - suite.addTest(unittest.makeSuite(TestGBKMap)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_codecmaps_hk.py ============================================================================== --- python/trunk/Lib/test/test_codecmaps_hk.py (original) +++ python/trunk/Lib/test/test_codecmaps_hk.py Wed Apr 25 19:29:52 2007 @@ -14,9 +14,7 @@ mapfileurl = 'http://people.freebsd.org/~perky/i18n/BIG5HKSCS.TXT' def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestBig5HKSCSMap)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_codecmaps_jp.py ============================================================================== --- python/trunk/Lib/test/test_codecmaps_jp.py (original) +++ python/trunk/Lib/test/test_codecmaps_jp.py Wed Apr 25 19:29:52 2007 @@ -61,13 +61,7 @@ def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestCP932Map)) - suite.addTest(unittest.makeSuite(TestEUCJPCOMPATMap)) - suite.addTest(unittest.makeSuite(TestSJISCOMPATMap)) - suite.addTest(unittest.makeSuite(TestEUCJISX0213Map)) - suite.addTest(unittest.makeSuite(TestSJISX0213Map)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_codecmaps_kr.py ============================================================================== --- python/trunk/Lib/test/test_codecmaps_kr.py (original) +++ python/trunk/Lib/test/test_codecmaps_kr.py Wed Apr 25 19:29:52 2007 @@ -34,11 +34,7 @@ pass_dectest = [('\\', u'\u20a9')] def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestCP949Map)) - suite.addTest(unittest.makeSuite(TestEUCKRMap)) - suite.addTest(unittest.makeSuite(TestJOHABMap)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_codecmaps_tw.py ============================================================================== --- python/trunk/Lib/test/test_codecmaps_tw.py (original) +++ python/trunk/Lib/test/test_codecmaps_tw.py Wed Apr 25 19:29:52 2007 @@ -25,10 +25,7 @@ ] def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestBIG5Map)) - suite.addTest(unittest.makeSuite(TestCP950Map)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_contextlib.py ============================================================================== --- python/trunk/Lib/test/test_contextlib.py (original) +++ python/trunk/Lib/test/test_contextlib.py Wed Apr 25 19:29:52 2007 @@ -9,7 +9,7 @@ import unittest import threading from contextlib import * # Tests __all__ -from test.test_support import run_suite +from test import test_support class ContextManagerTestCase(unittest.TestCase): @@ -332,9 +332,7 @@ # This is needed to make the test actually run under regrtest.py! def test_main(): - run_suite( - unittest.defaultTestLoader.loadTestsFromModule(sys.modules[__name__]) - ) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_ctypes.py ============================================================================== --- python/trunk/Lib/test/test_ctypes.py (original) +++ python/trunk/Lib/test/test_ctypes.py Wed Apr 25 19:29:52 2007 @@ -1,12 +1,12 @@ import unittest -from test.test_support import run_suite +from test.test_support import run_unittest import ctypes.test def test_main(): skipped, testcases = ctypes.test.get_tests(ctypes.test, "test_*.py", verbosity=0) suites = [unittest.makeSuite(t) for t in testcases] - run_suite(unittest.TestSuite(suites)) + run_unittest(unittest.TestSuite(suites)) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_datetime.py ============================================================================== --- python/trunk/Lib/test/test_datetime.py (original) +++ python/trunk/Lib/test/test_datetime.py Wed Apr 25 19:29:52 2007 @@ -128,7 +128,7 @@ # Base clase for testing a particular aspect of timedelta, time, date and # datetime comparisons. -class HarmlessMixedComparison(unittest.TestCase): +class HarmlessMixedComparison: # Test that __eq__ and __ne__ don't complain for mixed-type comparisons. # Subclasses must define 'theclass', and theclass(1, 1, 1) must be a @@ -167,7 +167,7 @@ ############################################################################# # timedelta tests -class TestTimeDelta(HarmlessMixedComparison): +class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase): theclass = timedelta @@ -514,7 +514,7 @@ class SubclassDate(date): sub_var = 1 -class TestDate(HarmlessMixedComparison): +class TestDate(HarmlessMixedComparison, unittest.TestCase): # Tests here should pass for both dates and datetimes, except for a # few tests that TestDateTime overrides. @@ -1596,7 +1596,7 @@ class SubclassTime(time): sub_var = 1 -class TestTime(HarmlessMixedComparison): +class TestTime(HarmlessMixedComparison, unittest.TestCase): theclass = time @@ -1879,7 +1879,7 @@ # A mixin for classes with a tzinfo= argument. Subclasses must define # theclass as a class atribute, and theclass(1, 1, 1, tzinfo=whatever) # must be legit (which is true for time and datetime). -class TZInfoBase(unittest.TestCase): +class TZInfoBase: def test_argument_passing(self): cls = self.theclass @@ -2039,7 +2039,7 @@ # Testing time objects with a non-None tzinfo. -class TestTimeTZ(TestTime, TZInfoBase): +class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase): theclass = time def test_empty(self): @@ -2287,7 +2287,7 @@ # Testing datetime objects with a non-None tzinfo. -class TestDateTimeTZ(TestDateTime, TZInfoBase): +class TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase): theclass = datetime def test_trivial(self): @@ -3248,31 +3248,13 @@ self.assertEqual(as_datetime, datetime_sc) self.assertEqual(datetime_sc, as_datetime) -def test_suite(): - allsuites = [unittest.makeSuite(klass, 'test') - for klass in (TestModule, - TestTZInfo, - TestTimeDelta, - TestDateOnly, - TestDate, - TestDateTime, - TestTime, - TestTimeTZ, - TestDateTimeTZ, - TestTimezoneConversions, - Oddballs, - ) - ] - return unittest.TestSuite(allsuites) - def test_main(): import gc import sys - thesuite = test_suite() lastrc = None while True: - test_support.run_suite(thesuite) + test_support.run_unittest(__name__) if 1: # change to 0, under a debug build, for some leak detection break gc.collect() Modified: python/trunk/Lib/test/test_email.py ============================================================================== --- python/trunk/Lib/test/test_email.py (original) +++ python/trunk/Lib/test/test_email.py Wed Apr 25 19:29:52 2007 @@ -4,10 +4,10 @@ import unittest # The specific tests now live in Lib/email/test from email.test.test_email import suite -from test.test_support import run_suite +from test import test_support def test_main(): - run_suite(suite()) + test_support.run_unittest(suite()) if __name__ == '__main__': test_main() Modified: python/trunk/Lib/test/test_email_codecs.py ============================================================================== --- python/trunk/Lib/test/test_email_codecs.py (original) +++ python/trunk/Lib/test/test_email_codecs.py Wed Apr 25 19:29:52 2007 @@ -9,7 +9,7 @@ def test_main(): suite = test_email_codecs.suite() suite.addTest(test_email_codecs_renamed.suite()) - test_support.run_suite(suite) + test_support.run_unittest(suite) if __name__ == '__main__': test_main() Modified: python/trunk/Lib/test/test_email_renamed.py ============================================================================== --- python/trunk/Lib/test/test_email_renamed.py (original) +++ python/trunk/Lib/test/test_email_renamed.py Wed Apr 25 19:29:52 2007 @@ -4,10 +4,10 @@ import unittest # The specific tests now live in Lib/email/test from email.test.test_email_renamed import suite -from test.test_support import run_suite +from test import test_support def test_main(): - run_suite(suite()) + test_support.run_unittest(suite()) if __name__ == '__main__': test_main() Modified: python/trunk/Lib/test/test_gettext.py ============================================================================== --- python/trunk/Lib/test/test_gettext.py (original) +++ python/trunk/Lib/test/test_gettext.py Wed Apr 25 19:29:52 2007 @@ -4,7 +4,7 @@ import gettext import unittest -from test.test_support import run_suite +from test import test_support # TODO: @@ -336,19 +336,8 @@ 'John Doe \nJane Foobar ') -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(GettextTestCase1)) - suite.addTest(unittest.makeSuite(GettextTestCase2)) - suite.addTest(unittest.makeSuite(PluralFormsTestCase)) - suite.addTest(unittest.makeSuite(UnicodeTranslationsTest)) - suite.addTest(unittest.makeSuite(WeirdMetadataTest)) - return suite - - def test_main(): - run_suite(suite()) - + test_support.run_unittest(__name__) if __name__ == '__main__': test_main() Modified: python/trunk/Lib/test/test_multibytecodec.py ============================================================================== --- python/trunk/Lib/test/test_multibytecodec.py (original) +++ python/trunk/Lib/test/test_multibytecodec.py Wed Apr 25 19:29:52 2007 @@ -219,13 +219,7 @@ myunichr(x).encode('iso_2022_jp', 'ignore') def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_MultibyteCodec)) - suite.addTest(unittest.makeSuite(Test_IncrementalEncoder)) - suite.addTest(unittest.makeSuite(Test_IncrementalDecoder)) - suite.addTest(unittest.makeSuite(Test_StreamWriter)) - suite.addTest(unittest.makeSuite(Test_ISO2022)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_optparse.py ============================================================================== --- python/trunk/Lib/test/test_optparse.py (original) +++ python/trunk/Lib/test/test_optparse.py Wed Apr 25 19:29:52 2007 @@ -1631,18 +1631,8 @@ "option -l: invalid long integer value: '0x12x'") -def _testclasses(): - mod = sys.modules[__name__] - return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] - -def suite(): - suite = unittest.TestSuite() - for testclass in _testclasses(): - suite.addTest(unittest.makeSuite(testclass)) - return suite - def test_main(): - test_support.run_suite(suite()) + test_support.run_unittest(__name__) if __name__ == '__main__': - unittest.main() + test_main() Modified: python/trunk/Lib/test/test_robotparser.py ============================================================================== --- python/trunk/Lib/test/test_robotparser.py (original) +++ python/trunk/Lib/test/test_robotparser.py Wed Apr 25 19:29:52 2007 @@ -135,8 +135,8 @@ RobotTest(7, doc, good, bad) def test_main(): - test_support.run_suite(tests) + test_support.run_unittest(tests) if __name__=='__main__': test_support.Verbose = 1 - test_support.run_suite(tests) + test_main() Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Wed Apr 25 19:29:52 2007 @@ -8,6 +8,7 @@ import socket import sys import warnings +import types class Error(Exception): """Base class for regression test exceptions.""" @@ -519,7 +520,7 @@ return result -def run_suite(suite, testclass=None): +def _run_suite(suite): """Run tests from a unittest.TestSuite-derived class.""" if verbose: runner = unittest.TextTestRunner(sys.stdout, verbosity=2) @@ -533,28 +534,26 @@ elif len(result.failures) == 1 and not result.errors: err = result.failures[0][1] else: - if testclass is None: - msg = "errors occurred; run in verbose mode for details" - else: - msg = "errors occurred in %s.%s" \ - % (testclass.__module__, testclass.__name__) + msg = "errors occurred; run in verbose mode for details" raise TestFailed(msg) raise TestFailed(err) def run_unittest(*classes): """Run tests from unittest.TestCase-derived classes.""" + valid_types = (unittest.TestSuite, unittest.TestCase) suite = unittest.TestSuite() for cls in classes: - if isinstance(cls, (unittest.TestSuite, unittest.TestCase)): + if isinstance(cls, str): + if cls in sys.modules: + suite.addTest(unittest.findTestCases(sys.modules[cls])) + else: + raise ValueError("str arguments must be keys in sys.modules") + elif isinstance(cls, valid_types): suite.addTest(cls) else: suite.addTest(unittest.makeSuite(cls)) - if len(classes)==1: - testclass = classes[0] - else: - testclass = None - run_suite(suite, testclass) + _run_suite(suite) #======================================================================= Modified: python/trunk/Lib/test/test_threading_local.py ============================================================================== --- python/trunk/Lib/test/test_threading_local.py (original) +++ python/trunk/Lib/test/test_threading_local.py Wed Apr 25 19:29:52 2007 @@ -20,7 +20,7 @@ setUp=setUp, tearDown=tearDown) ) - test_support.run_suite(suite) + test_support.run_unittest(suite) if __name__ == '__main__': test_main() Modified: python/trunk/Lib/test/test_unicode.py ============================================================================== --- python/trunk/Lib/test/test_unicode.py (original) +++ python/trunk/Lib/test/test_unicode.py Wed Apr 25 19:29:52 2007 @@ -822,7 +822,7 @@ def test_main(): - test_support.run_unittest(UnicodeTest) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_unicode_file.py ============================================================================== --- python/trunk/Lib/test/test_unicode_file.py (original) +++ python/trunk/Lib/test/test_unicode_file.py Wed Apr 25 19:29:52 2007 @@ -5,7 +5,7 @@ import unicodedata import unittest -from test.test_support import run_suite, TestSkipped, TESTFN_UNICODE +from test.test_support import run_unittest, TestSkipped, TESTFN_UNICODE from test.test_support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE try: TESTFN_ENCODED = TESTFN_UNICODE.encode(TESTFN_ENCODING) @@ -205,9 +205,7 @@ False) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestUnicodeFiles)) - run_suite(suite) + run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/test/test_wsgiref.py ============================================================================== --- python/trunk/Lib/test/test_wsgiref.py (original) +++ python/trunk/Lib/test/test_wsgiref.py Wed Apr 25 19:29:52 2007 @@ -1,5 +1,5 @@ from __future__ import nested_scopes # Backward compat for 2.1 -from unittest import TestSuite, TestCase, makeSuite +from unittest import TestCase from wsgiref.util import setup_testing_defaults from wsgiref.headers import Headers from wsgiref.handlers import BaseHandler, BaseCGIHandler @@ -11,6 +11,7 @@ from SocketServer import BaseServer import re, sys +from test import test_support class MockServer(WSGIServer): """Non-socket HTTP server""" @@ -575,11 +576,7 @@ # This epilogue is needed for compatibility with the Python 2.5 regrtest module def test_main(): - import unittest - from test.test_support import run_suite - run_suite( - unittest.defaultTestLoader.loadTestsFromModule(sys.modules[__name__]) - ) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() From python-checkins at python.org Wed Apr 25 19:37:41 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 25 Apr 2007 19:37:41 +0200 (CEST) Subject: [Python-checkins] r54957 - python/trunk/Lib/test/test_datetime.py Message-ID: <20070425173741.102E91E400C@bag.python.org> Author: collin.winter Date: Wed Apr 25 19:37:35 2007 New Revision: 54957 Modified: python/trunk/Lib/test/test_datetime.py Log: Remove functionality from test_datetime.test_main() that does reference count checking; 'regrtest.py -R' is the way to do this kind of testing. Modified: python/trunk/Lib/test/test_datetime.py ============================================================================== --- python/trunk/Lib/test/test_datetime.py (original) +++ python/trunk/Lib/test/test_datetime.py Wed Apr 25 19:37:35 2007 @@ -3249,26 +3249,7 @@ self.assertEqual(datetime_sc, as_datetime) def test_main(): - import gc - import sys - - lastrc = None - while True: - test_support.run_unittest(__name__) - if 1: # change to 0, under a debug build, for some leak detection - break - gc.collect() - if gc.garbage: - raise SystemError("gc.garbage not empty after test run: %r" % - gc.garbage) - if hasattr(sys, 'gettotalrefcount'): - thisrc = sys.gettotalrefcount() - print >> sys.stderr, '*' * 10, 'total refs:', thisrc, - if lastrc: - print >> sys.stderr, 'delta:', thisrc - lastrc - else: - print >> sys.stderr - lastrc = thisrc + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() From python-checkins at python.org Wed Apr 25 19:57:54 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 25 Apr 2007 19:57:54 +0200 (CEST) Subject: [Python-checkins] r54958 - python/trunk/Lib/test/test_support.py Message-ID: <20070425175754.5041A1E400D@bag.python.org> Author: collin.winter Date: Wed Apr 25 19:57:53 2007 New Revision: 54958 Modified: python/trunk/Lib/test/test_support.py Log: Change test_support.have_unicode to use True/False instead of 1/0. Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Wed Apr 25 19:57:53 2007 @@ -133,9 +133,9 @@ try: unicode - have_unicode = 1 + have_unicode = True except NameError: - have_unicode = 0 + have_unicode = False is_jython = sys.platform.startswith('java') From buildbot at python.org Wed Apr 25 20:37:45 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 18:37:45 +0000 Subject: [Python-checkins] buildbot warnings in x86 mvlgcc trunk Message-ID: <20070425183745.A6A481E400C@bag.python.org> The Buildbot has detected a new failure of x86 mvlgcc trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520mvlgcc%2520trunk/builds/486 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings test Excerpt from the test logfile: Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 93, in run svr.serve_a_few() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_socketserver.py", line 35, in serve_a_few self.handle_request() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 224, in handle_request self.handle_error(request, client_address) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 222, in handle_request self.process_request(request, client_address) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 429, in process_request self.collect_children() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/SocketServer.py", line 425, in collect_children self.active_children.remove(pid) ValueError: list.remove(x): x not in list 1 test failed: test_socketserver make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Apr 25 20:47:26 2007 From: python-checkins at python.org (tim.peters) Date: Wed, 25 Apr 2007 20:47:26 +0200 (CEST) Subject: [Python-checkins] r54959 - python/trunk/Demo/parser/unparse.py Message-ID: <20070425184726.916161E400C@bag.python.org> Author: tim.peters Date: Wed Apr 25 20:47:18 2007 New Revision: 54959 Modified: python/trunk/Demo/parser/unparse.py Log: Whitespace normalization. Modified: python/trunk/Demo/parser/unparse.py ============================================================================== --- python/trunk/Demo/parser/unparse.py (original) +++ python/trunk/Demo/parser/unparse.py Wed Apr 25 20:47:18 2007 @@ -10,7 +10,7 @@ seq = iter(seq) try: f(seq.next()) - except StopIteration: + except StopIteration: pass else: for x in seq: From python-checkins at python.org Wed Apr 25 20:48:36 2007 From: python-checkins at python.org (tim.peters) Date: Wed, 25 Apr 2007 20:48:36 +0200 (CEST) Subject: [Python-checkins] r54960 - python/trunk/Lib/test/test_ftplib.py python/trunk/Lib/test/test_poplib.py python/trunk/Lib/test/test_smtplib.py python/trunk/Lib/test/test_telnetlib.py python/trunk/Lib/test/warning_tests.py Message-ID: <20070425184836.6AEE31E400C@bag.python.org> Author: tim.peters Date: Wed Apr 25 20:48:35 2007 New Revision: 54960 Modified: python/trunk/Lib/test/test_ftplib.py (props changed) python/trunk/Lib/test/test_poplib.py (props changed) python/trunk/Lib/test/test_smtplib.py (props changed) python/trunk/Lib/test/test_telnetlib.py (props changed) python/trunk/Lib/test/warning_tests.py (props changed) Log: Set missing svn:eol-style property on text files. From python-checkins at python.org Wed Apr 25 20:54:44 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 25 Apr 2007 20:54:44 +0200 (CEST) Subject: [Python-checkins] r54961 - python/trunk/Lib/test/test_support.py Message-ID: <20070425185444.290441E400C@bag.python.org> Author: collin.winter Date: Wed Apr 25 20:54:36 2007 New Revision: 54961 Modified: python/trunk/Lib/test/test_support.py Log: Import and raise statement cleanup. Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Wed Apr 25 20:54:36 2007 @@ -1,14 +1,17 @@ """Supporting definitions for the Python regression tests.""" if __name__ != 'test.test_support': - raise ImportError, 'test_support must be imported from the test package' + raise ImportError('test_support must be imported from the test package') import contextlib import errno import socket import sys +import os +import os.path import warnings import types +import unittest class Error(Exception): """Base class for regression test exceptions.""" @@ -57,7 +60,6 @@ pass def unlink(filename): - import os try: os.unlink(filename) except OSError: @@ -67,7 +69,6 @@ '''"Forget" a module was ever imported by removing it from sys.modules and deleting any .pyc and .pyo files.''' unload(modname) - import os for dirname in sys.path: unlink(os.path.join(dirname, modname + os.extsep + 'pyc')) # Deleting the .pyo file cannot be within the 'try' for the .pyc since @@ -99,7 +100,6 @@ tests and we don't try multiple ports, the test can fails. This makes the test more robust.""" - import socket, errno # some random ports that hopefully no one is listening on. for port in [preferred_port, 9907, 10243, 32999]: try: @@ -110,7 +110,7 @@ raise print >>sys.__stderr__, \ ' WARNING: failed to listen on port %d, trying another' % port - raise TestFailed, 'unable to find port to listen on' + raise TestFailed('unable to find port to listen on') FUZZ = 1e-6 @@ -139,7 +139,6 @@ is_jython = sys.platform.startswith('java') -import os # Filename used for testing if os.name == 'java': # Jython disallows @ in module names @@ -202,13 +201,12 @@ if fp is not None: fp.close() unlink(TESTFN) -del os, fp +del fp def findfile(file, here=__file__): """Try to find a file on sys.path and the working directory. If it is not found the argument passed to the function is returned (this does not necessarily signal failure; could still be the legitimate path).""" - import os if os.path.isabs(file): return file path = sys.path @@ -240,7 +238,7 @@ """ if not (a == b): - raise TestFailed, "%r == %r" % (a, b) + raise TestFailed("%r == %r" % (a, b)) def sortdict(dict): "Like repr(dict), but in sorted order." @@ -260,7 +258,6 @@ def open_urlresource(url): import urllib, urlparse - import os.path filename = urlparse.urlparse(url)[2].split('/')[-1] # '/': it's URL! @@ -325,8 +322,7 @@ a context manager.""" def __init__(self): - from os import environ - self._environ = environ + self._environ = os.environ self._unset = set() self._reset = dict() @@ -508,10 +504,7 @@ return wrapper #======================================================================= -# Preliminary PyUNIT integration. - -import unittest - +# unittest integration. class BasicTestRunner: def run(self, test): @@ -619,7 +612,6 @@ # Reap all our dead child processes so we don't leave zombies around. # These hog resources and might be causing some of the buildbots to die. - import os if hasattr(os, 'waitpid'): any_process = -1 while True: From python-checkins at python.org Wed Apr 25 21:26:48 2007 From: python-checkins at python.org (barry.warsaw) Date: Wed, 25 Apr 2007 21:26:48 +0200 (CEST) Subject: [Python-checkins] r54962 - python/branches/release25-maint/Lib/email/__init__.py Message-ID: <20070425192648.1153F1E400C@bag.python.org> Author: barry.warsaw Date: Wed Apr 25 21:26:37 2007 New Revision: 54962 Modified: python/branches/release25-maint/Lib/email/__init__.py Log: bump email package version to 4.0.2 Modified: python/branches/release25-maint/Lib/email/__init__.py ============================================================================== --- python/branches/release25-maint/Lib/email/__init__.py (original) +++ python/branches/release25-maint/Lib/email/__init__.py Wed Apr 25 21:26:37 2007 @@ -4,7 +4,7 @@ """A package for parsing, handling, and generating email messages.""" -__version__ = '4.0.1' +__version__ = '4.0.2' __all__ = [ # Old names From python-checkins at python.org Wed Apr 25 21:30:49 2007 From: python-checkins at python.org (barry.warsaw) Date: Wed, 25 Apr 2007 21:30:49 +0200 (CEST) Subject: [Python-checkins] r54963 - sandbox/trunk/emailpkg/4_0 Message-ID: <20070425193049.256C61E400C@bag.python.org> Author: barry.warsaw Date: Wed Apr 25 21:30:45 2007 New Revision: 54963 Modified: sandbox/trunk/emailpkg/4_0/ (props changed) Log: Grab the email package from Python 2.5, not from the trunk (i.e. not from Python 2.6 dev). From python-checkins at python.org Wed Apr 25 21:47:58 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 25 Apr 2007 21:47:58 +0200 (CEST) Subject: [Python-checkins] r54964 - in sandbox/trunk/2to3: example.py fixes/fix_ws_comma.py pytree.py refactor.py Message-ID: <20070425194758.A29AD1E400C@bag.python.org> Author: guido.van.rossum Date: Wed Apr 25 21:47:49 2007 New Revision: 54964 Added: sandbox/trunk/2to3/fixes/fix_ws_comma.py (contents, props changed) Modified: sandbox/trunk/2to3/example.py sandbox/trunk/2to3/pytree.py sandbox/trunk/2to3/refactor.py Log: Example fixer that normalizes the whitespace around commas (and around colons in dict displays). This required a few minor tweaks elsewhere. Modified: sandbox/trunk/2to3/example.py ============================================================================== --- sandbox/trunk/2to3/example.py (original) +++ sandbox/trunk/2to3/example.py Wed Apr 25 21:47:49 2007 @@ -65,6 +65,13 @@ def foo(): pass # body indented by tab +def test_ws_comma(): + yield 1,2 ,3 + f(1,2 ,3) + `a ,b` + def f(a,b ,c): pass + { a:b,c:d , e : f } + def apply_examples(): x = apply(f, g + h) y = apply(f, g, h) Added: sandbox/trunk/2to3/fixes/fix_ws_comma.py ============================================================================== --- (empty file) +++ sandbox/trunk/2to3/fixes/fix_ws_comma.py Wed Apr 25 21:47:49 2007 @@ -0,0 +1,37 @@ +"""Fixer that changes 'a ,b' into 'a, b'. + +This also changes '{a :b}' into '{a: b}', but does not touch other +uses of colons. It does not touch other uses of whitespace. + +""" + +import pytree +from pgen2 import token +from fixes import basefix + +class FixWsComma(basefix.BaseFix): + + PATTERN = """ + any<(not(',') any)+ ',' ((not(',') any)+ ',')* [not(',') any]> + """ + + COMMA = pytree.Leaf(token.COMMA, ",") + COLON = pytree.Leaf(token.COLON, ":") + SEPS = (COMMA, COLON) + + def transform(self, node): + new = node.clone() + comma = False + for child in new.children: + if child in self.SEPS: + prefix = child.get_prefix() + if prefix.isspace() and "\n" not in prefix: + child.set_prefix("") + comma = True + else: + if comma: + prefix = child.get_prefix() + if not prefix: + child.set_prefix(" ") + comma = False + return new Modified: sandbox/trunk/2to3/pytree.py ============================================================================== --- sandbox/trunk/2to3/pytree.py (original) +++ sandbox/trunk/2to3/pytree.py Wed Apr 25 21:47:49 2007 @@ -460,8 +460,9 @@ """Initializer. Takes optional type, content, and name. The type, if given, must be a symbol type (>= 256). If the - type is None, the content must be None, and this matches *any* - single node (leaf or not). + type is None this matches *any* single node (leaf or not), + except if content is not None, in which it only matches + non-leaf nodes that also match the content pattern. The content, if not None, must be a sequence of Patterns that must match the node's children exactly. If the content is @@ -472,8 +473,6 @@ """ if type is not None: assert type >= 256, type - else: - assert content is None, repr(content) if content is not None: assert not isinstance(content, basestring), repr(content) content = list(content) Modified: sandbox/trunk/2to3/refactor.py ============================================================================== --- sandbox/trunk/2to3/refactor.py (original) +++ sandbox/trunk/2to3/refactor.py Wed Apr 25 21:47:49 2007 @@ -256,7 +256,8 @@ for fixer in self.fixers: if fixer.match(node): new = fixer.transform(node) - if new is not None and new != node: + if new is not None and (new != node or + str(new) != str(node)): node.replace(new) changes += 1 elif tree.was_changed: From python-checkins at python.org Wed Apr 25 21:49:04 2007 From: python-checkins at python.org (barry.warsaw) Date: Wed, 25 Apr 2007 21:49:04 +0200 (CEST) Subject: [Python-checkins] r54965 - sandbox/trunk/emailpkg/4_0/MANIFEST sandbox/trunk/emailpkg/4_0/README.txt sandbox/trunk/emailpkg/4_0/ez_setup.py sandbox/trunk/emailpkg/4_0/setup.py Message-ID: <20070425194904.966F51E400C@bag.python.org> Author: barry.warsaw Date: Wed Apr 25 21:48:57 2007 New Revision: 54965 Added: sandbox/trunk/emailpkg/4_0/ez_setup.py Removed: sandbox/trunk/emailpkg/4_0/MANIFEST Modified: sandbox/trunk/emailpkg/4_0/README.txt sandbox/trunk/emailpkg/4_0/setup.py Log: Use setuptools so that we can create eggs. Updates for email 4.0.2. Deleted: /sandbox/trunk/emailpkg/4_0/MANIFEST ============================================================================== --- /sandbox/trunk/emailpkg/4_0/MANIFEST Wed Apr 25 21:48:57 2007 +++ (empty file) @@ -1,133 +0,0 @@ -setup.py -testall.py -README.txt -email/__init__.py -email/_parseaddr.py -email/base64mime.py -email/charset.py -email/encoders.py -email/errors.py -email/feedparser.py -email/generator.py -email/header.py -email/iterators.py -email/message.py -email/parser.py -email/quoprimime.py -email/utils.py -email/mime/__init__.py -email/mime/application.py -email/mime/audio.py -email/mime/base.py -email/mime/image.py -email/mime/message.py -email/mime/multipart.py -email/mime/nonmultipart.py -email/mime/text.py -email/test/__init__.py -email/test/test_email.py -email/test/test_email_codecs.py -email/test/test_email_renamed.py -email/test/test_email_codecs_renamed.py -email/test/test_email_torture.py -email/test/data/PyBanner048.gif -email/test/data/audiotest.au -email/test/data/msg_01.txt -email/test/data/msg_02.txt -email/test/data/msg_03.txt -email/test/data/msg_04.txt -email/test/data/msg_05.txt -email/test/data/msg_06.txt -email/test/data/msg_07.txt -email/test/data/msg_08.txt -email/test/data/msg_09.txt -email/test/data/msg_10.txt -email/test/data/msg_11.txt -email/test/data/msg_12.txt -email/test/data/msg_12a.txt -email/test/data/msg_13.txt -email/test/data/msg_14.txt -email/test/data/msg_15.txt -email/test/data/msg_16.txt -email/test/data/msg_17.txt -email/test/data/msg_19.txt -email/test/data/msg_20.txt -email/test/data/msg_21.txt -email/test/data/msg_22.txt -email/test/data/msg_23.txt -email/test/data/msg_24.txt -email/test/data/msg_25.txt -email/test/data/msg_26.txt -email/test/data/msg_27.txt -email/test/data/msg_28.txt -email/test/data/msg_29.txt -email/test/data/msg_30.txt -email/test/data/msg_31.txt -email/test/data/msg_32.txt -email/test/data/msg_33.txt -email/test/data/msg_34.txt -email/test/data/msg_35.txt -email/test/data/msg_35.txt -email/test/data/msg_36.txt -email/test/data/msg_37.txt -email/test/data/msg_38.txt -email/test/data/msg_39.txt -email/test/data/msg_40.txt -email/test/data/msg_41.txt -email/test/data/msg_42.txt -email/test/data/msg_43.txt -email/test/data/msg_44.txt -moredata/crispin-torture.txt -docs/about.html -docs/blank.png -docs/contents.png -docs/email-dir.txt -docs/email-mime.txt -docs/email-pkg-history.html -docs/email-simple.txt -docs/email-unpack.txt -docs/index.html -docs/index.png -docs/mimelib.css -docs/mimelib.html -docs/mimelib.pdf -docs/module-email.charset.html -docs/module-email.encoders.html -docs/module-email.errors.html -docs/module-email.generator.html -docs/module-email.header.html -docs/module-email.html -docs/module-email.iterators.html -docs/module-email.message.html -docs/module-email.mime.text.html -docs/module-email.parser.html -docs/module-email.utils.html -docs/modules.png -docs/next.png -docs/node1.html -docs/node16.html -docs/node17.html -docs/node18.html -docs/node5.html -docs/node6.html -docs/node7.html -docs/previous.png -docs/pyfav.png -docs/up.png -manual/Makefile -manual/email-dir.py -manual/email-mime.py -manual/email-simple.py -manual/email-unpack.py -manual/email.tex -manual/emailcharsets.tex -manual/emailencoders.tex -manual/emailexc.tex -manual/emailgenerator.tex -manual/emailheaders.tex -manual/emailiter.tex -manual/emailmessage.tex -manual/emailmimebase.tex -manual/emailparser.tex -manual/emailutil.tex -manual/mimelib.tex Modified: sandbox/trunk/emailpkg/4_0/README.txt ============================================================================== --- sandbox/trunk/emailpkg/4_0/README.txt (original) +++ sandbox/trunk/emailpkg/4_0/README.txt Wed Apr 25 21:48:57 2007 @@ -1,5 +1,5 @@ email -- a mail and MIME handling package -Copyright (C) 2001-2006 Python Software Foundation +Copyright (C) 2001-2007 Python Software Foundation Introduction @@ -12,9 +12,9 @@ email related RFCs such as 2045-2047 (the MIME RFCs) and 2231. This version is identical to the package available in Python 2.5. It is - being made available as a standalone distutils package for use in older - Python releases. A minimum of Python 2.3 is required. Because the email - package is part of Python, it is covered by the PSF license for Python, as + being made available as a standalone package for use in older Python + releases. A minimum of Python 2.3 is required. Because the email package + is part of Python, it is covered by the PSF license for Python, as described in the LICENSE.txt file. Added: sandbox/trunk/emailpkg/4_0/ez_setup.py ============================================================================== --- (empty file) +++ sandbox/trunk/emailpkg/4_0/ez_setup.py Wed Apr 25 21:48:57 2007 @@ -0,0 +1,228 @@ +#!python +"""Bootstrap setuptools installation + +If you want to use setuptools in your package's setup.py, just include this +file in the same directory with it, and add this to the top of your setup.py:: + + from ez_setup import use_setuptools + use_setuptools() + +If you want to require a specific version of setuptools, set a download +mirror, or use an alternate download directory, you can do so by supplying +the appropriate options to ``use_setuptools()``. + +This file can also be run as a script to install or upgrade setuptools. +""" +import sys +DEFAULT_VERSION = "0.6c5" +DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3] + +md5_data = { + 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', + 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', + 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', + 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', + 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', + 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', + 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', + 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', + 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', + 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', + 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', + 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', + 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', + 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', + 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', + 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', + 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', + 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', + 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', + 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', + 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', +} + +import sys, os + +def _validate_md5(egg_name, data): + if egg_name in md5_data: + from md5 import md5 + digest = md5(data).hexdigest() + if digest != md5_data[egg_name]: + print >>sys.stderr, ( + "md5 validation of %s failed! (Possible download problem?)" + % egg_name + ) + sys.exit(2) + return data + + +def use_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, + download_delay=15 +): + """Automatically find/download setuptools and make it available on sys.path + + `version` should be a valid setuptools version number that is available + as an egg for download under the `download_base` URL (which should end with + a '/'). `to_dir` is the directory where setuptools will be downloaded, if + it is not already available. If `download_delay` is specified, it should + be the number of seconds that will be paused before initiating a download, + should one be required. If an older version of setuptools is installed, + this routine will print a message to ``sys.stderr`` and raise SystemExit in + an attempt to abort the calling script. + """ + try: + import setuptools + if setuptools.__version__ == '0.0.1': + print >>sys.stderr, ( + "You have an obsolete version of setuptools installed. Please\n" + "remove it from your system entirely before rerunning this script." + ) + sys.exit(2) + except ImportError: + egg = download_setuptools(version, download_base, to_dir, download_delay) + sys.path.insert(0, egg) + import setuptools; setuptools.bootstrap_install_from = egg + + import pkg_resources + try: + pkg_resources.require("setuptools>="+version) + + except pkg_resources.VersionConflict, e: + # XXX could we install in a subprocess here? + print >>sys.stderr, ( + "The required version of setuptools (>=%s) is not available, and\n" + "can't be installed while this script is running. Please install\n" + " a more recent version first.\n\n(Currently using %r)" + ) % (version, e.args[0]) + sys.exit(2) + +def download_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, + delay = 15 +): + """Download setuptools from a specified location and return its filename + + `version` should be a valid setuptools version number that is available + as an egg for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download attempt. + """ + import urllib2, shutil + egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) + url = download_base + egg_name + saveto = os.path.join(to_dir, egg_name) + src = dst = None + if not os.path.exists(saveto): # Avoid repeated downloads + try: + from distutils import log + if delay: + log.warn(""" +--------------------------------------------------------------------------- +This script requires setuptools version %s to run (even to display +help). I will attempt to download it for you (from +%s), but +you may need to enable firewall access for this script first. +I will start the download in %d seconds. + +(Note: if this machine does not have network access, please obtain the file + + %s + +and place it in this directory before rerunning this script.) +---------------------------------------------------------------------------""", + version, download_base, delay, url + ); from time import sleep; sleep(delay) + log.warn("Downloading %s", url) + src = urllib2.urlopen(url) + # Read/write all in one block, so we don't create a corrupt file + # if the download is interrupted. + data = _validate_md5(egg_name, src.read()) + dst = open(saveto,"wb"); dst.write(data) + finally: + if src: src.close() + if dst: dst.close() + return os.path.realpath(saveto) + +def main(argv, version=DEFAULT_VERSION): + """Install or upgrade setuptools and EasyInstall""" + + try: + import setuptools + except ImportError: + egg = None + try: + egg = download_setuptools(version, delay=0) + sys.path.insert(0,egg) + from setuptools.command.easy_install import main + return main(list(argv)+[egg]) # we're done here + finally: + if egg and os.path.exists(egg): + os.unlink(egg) + else: + if setuptools.__version__ == '0.0.1': + # tell the user to uninstall obsolete version + use_setuptools(version) + + req = "setuptools>="+version + import pkg_resources + try: + pkg_resources.require(req) + except pkg_resources.VersionConflict: + try: + from setuptools.command.easy_install import main + except ImportError: + from easy_install import main + main(list(argv)+[download_setuptools(delay=0)]) + sys.exit(0) # try to force an exit + else: + if argv: + from setuptools.command.easy_install import main + main(argv) + else: + print "Setuptools version",version,"or greater has been installed." + print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' + + + +def update_md5(filenames): + """Update our built-in md5 registry""" + + import re + from md5 import md5 + + for name in filenames: + base = os.path.basename(name) + f = open(name,'rb') + md5_data[base] = md5(f.read()).hexdigest() + f.close() + + data = [" %r: %r,\n" % it for it in md5_data.items()] + data.sort() + repl = "".join(data) + + import inspect + srcfile = inspect.getsourcefile(sys.modules[__name__]) + f = open(srcfile, 'rb'); src = f.read(); f.close() + + match = re.search("\nmd5_data = {\n([^}]+)}", src) + if not match: + print >>sys.stderr, "Internal error!" + sys.exit(2) + + src = src[:match.start(1)] + repl + src[match.end(1):] + f = open(srcfile,'w') + f.write(src) + f.close() + + +if __name__=='__main__': + if len(sys.argv)>2 and sys.argv[1]=='--md5update': + update_md5(sys.argv[2:]) + else: + main(sys.argv[1:]) + + + + + Modified: sandbox/trunk/emailpkg/4_0/setup.py ============================================================================== --- sandbox/trunk/emailpkg/4_0/setup.py (original) +++ sandbox/trunk/emailpkg/4_0/setup.py Wed Apr 25 21:48:57 2007 @@ -1,26 +1,23 @@ -#! /usr/bin/env python -# -# Copyright (C) 2001-2006 Python Software Foundation - -# Standard distutils setup.py install script for the `mimelib' library, a next -# generation MIME library for Python. To install into your existing Python -# distribution, run the following at the command line: -# -# % python setup.py install - -import sys -from os.path import basename - -from distutils.core import setup -from distutils.command.install_lib import install_lib +# Copyright (C) 2001-2007 Python Software Foundation +import ez_setup +ez_setup.use_setuptools() import email -setup(name='email', - version=email.__version__, - description='Standalone email package', - author='Barry Warsaw', - author_email='barry at python.org', - url='http://www.python.org/sigs/email-sig', - packages=['email', 'email.mime'], - ) +from setuptools import setup, find_packages + +setup( + name = 'email', + version = email.__version__, + description = 'Standalone email package', + long_description = """\ +This is the standalone email package. This is a copy of what's available in +Python but you may want to use the standalone version if you want the latest +and greatest email package, even in older Pythons.""", + author = 'Email SIG', + author_email = 'email-sig at python.org', + url = 'http://www.python.org/sigs/email-sig', + keywords = 'email', + license = 'Python software Foundation', + packages = find_packages(), + ) From python-checkins at python.org Wed Apr 25 21:51:57 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 25 Apr 2007 21:51:57 +0200 (CEST) Subject: [Python-checkins] r54966 - in sandbox/trunk: 2to3/fixes/fix_intern.py 2to3/fixes/fix_numliterals.py Doc/2.5-pr.txt Doc/func-example.py decimal-c/README.txt decimal-c/_decimal.c decimal-c/decimal.h decimal-c/decimal.py decimal-c/setup.py decimal-c/test_decimal.py hotbuffer/Modules/_hotbuf.c import_in_py/importbench.py mailbox/mailbox-msg-lockfix.py pdb/Doc/tools/buildindex.py pdb/Doc/tools/indfix.py pdb/Doc/tools/patchlevel.h pdb/Doc/tools/toc2bkm.py pdb/README.txt pdb/mconnection.py pdb/mpdb.py pdb/mproc.py pdb/mqueue.py pdb/mremote.py pdb/mthread.py pdb/patches/11-08-06-sigtestexample.py pdb/patches/27-07-06-sighandler.py pdb/patches/30-05-06-pdb.py pdb/patches/31-07-06-sighandler.py pdb/patches/31-07-06-test.py pdb/pdbserver.py pdb/test/files/proc.py pdb/test/files/thread_script.py pdb/test/support.py pdb/test/test_mconnection.py pdb/test/test_mpdb.py pdb/test/test_mthread.py pdb/test/test_process.py pep3101/README.txt pep3101/StringFormat.py pep3101/doctests/README.txt pep3101/doctests/basic_errors.txt pep3101/doctests/basic_examples.txt pep3101/doctests/basic_torture.txt pep3101/doctests/test.py pep3101/loadpep.py pep3101/pep3101.c pep3101/pep3101.h pep3101/pep_differences.txt pep3101/setup.py pep3101/stringformat.c pep3101/test_simpleformat.py pep3101/unicodeformat.c refactor/concrete.py refactor/example.py refactor/has_key.py rjsh-pybench/Empty.py rjsh-pybench/NewInstances.py seealso/convert-python-faqs.py seealso/make-seealso.py seealso/parse-seealso.py setuptools/setuptools/tests/win_script_wrapper.txt stringbench/stringbench.py tests/test_sax.py tests/test_saxgen.py trackers/trackers.txt welease/README.txt welease/welease.py Message-ID: <20070425195157.795651E4013@bag.python.org> Author: guido.van.rossum Date: Wed Apr 25 21:51:51 2007 New Revision: 54966 Modified: sandbox/trunk/2to3/fixes/fix_intern.py (props changed) sandbox/trunk/2to3/fixes/fix_numliterals.py (props changed) sandbox/trunk/Doc/2.5-pr.txt (props changed) sandbox/trunk/Doc/func-example.py (props changed) sandbox/trunk/decimal-c/README.txt (props changed) sandbox/trunk/decimal-c/_decimal.c (props changed) sandbox/trunk/decimal-c/decimal.h (props changed) sandbox/trunk/decimal-c/decimal.py (props changed) sandbox/trunk/decimal-c/setup.py (props changed) sandbox/trunk/decimal-c/test_decimal.py (props changed) sandbox/trunk/hotbuffer/Modules/_hotbuf.c (props changed) sandbox/trunk/import_in_py/importbench.py (props changed) sandbox/trunk/mailbox/mailbox-msg-lockfix.py (props changed) sandbox/trunk/pdb/Doc/tools/buildindex.py (props changed) sandbox/trunk/pdb/Doc/tools/indfix.py (props changed) sandbox/trunk/pdb/Doc/tools/patchlevel.h (props changed) sandbox/trunk/pdb/Doc/tools/toc2bkm.py (props changed) sandbox/trunk/pdb/README.txt (contents, props changed) sandbox/trunk/pdb/mconnection.py (contents, props changed) sandbox/trunk/pdb/mpdb.py (props changed) sandbox/trunk/pdb/mproc.py (props changed) sandbox/trunk/pdb/mqueue.py (props changed) sandbox/trunk/pdb/mremote.py (props changed) sandbox/trunk/pdb/mthread.py (props changed) sandbox/trunk/pdb/patches/11-08-06-sigtestexample.py (props changed) sandbox/trunk/pdb/patches/27-07-06-sighandler.py (props changed) sandbox/trunk/pdb/patches/30-05-06-pdb.py (props changed) sandbox/trunk/pdb/patches/31-07-06-sighandler.py (props changed) sandbox/trunk/pdb/patches/31-07-06-test.py (props changed) sandbox/trunk/pdb/pdbserver.py (props changed) sandbox/trunk/pdb/test/files/proc.py (props changed) sandbox/trunk/pdb/test/files/thread_script.py (props changed) sandbox/trunk/pdb/test/support.py (props changed) sandbox/trunk/pdb/test/test_mconnection.py (props changed) sandbox/trunk/pdb/test/test_mpdb.py (props changed) sandbox/trunk/pdb/test/test_mthread.py (props changed) sandbox/trunk/pdb/test/test_process.py (props changed) sandbox/trunk/pep3101/README.txt (props changed) sandbox/trunk/pep3101/StringFormat.py (props changed) sandbox/trunk/pep3101/doctests/README.txt (props changed) sandbox/trunk/pep3101/doctests/basic_errors.txt (props changed) sandbox/trunk/pep3101/doctests/basic_examples.txt (props changed) sandbox/trunk/pep3101/doctests/basic_torture.txt (props changed) sandbox/trunk/pep3101/doctests/test.py (props changed) sandbox/trunk/pep3101/loadpep.py (props changed) sandbox/trunk/pep3101/pep3101.c (props changed) sandbox/trunk/pep3101/pep3101.h (props changed) sandbox/trunk/pep3101/pep_differences.txt (props changed) sandbox/trunk/pep3101/setup.py (props changed) sandbox/trunk/pep3101/stringformat.c (props changed) sandbox/trunk/pep3101/test_simpleformat.py (props changed) sandbox/trunk/pep3101/unicodeformat.c (props changed) sandbox/trunk/refactor/concrete.py (props changed) sandbox/trunk/refactor/example.py (props changed) sandbox/trunk/refactor/has_key.py (props changed) sandbox/trunk/rjsh-pybench/Empty.py (contents, props changed) sandbox/trunk/rjsh-pybench/NewInstances.py (props changed) sandbox/trunk/seealso/convert-python-faqs.py (props changed) sandbox/trunk/seealso/make-seealso.py (props changed) sandbox/trunk/seealso/parse-seealso.py (props changed) sandbox/trunk/setuptools/setuptools/tests/win_script_wrapper.txt (contents, props changed) sandbox/trunk/stringbench/stringbench.py (props changed) sandbox/trunk/tests/test_sax.py (props changed) sandbox/trunk/tests/test_saxgen.py (props changed) sandbox/trunk/trackers/trackers.txt (props changed) sandbox/trunk/welease/README.txt (props changed) sandbox/trunk/welease/welease.py (props changed) Log: Setting svn:eol properties everywhere where they weren't set yet. Modified: sandbox/trunk/pdb/README.txt ============================================================================== --- sandbox/trunk/pdb/README.txt (original) +++ sandbox/trunk/pdb/README.txt Wed Apr 25 21:51:51 2007 @@ -1,65 +1,65 @@ --=[Pdb Improvements]=- - --=[Author: Matt Fleming ]=- --=[Mentor: Robert L. Bernstein]=- - --=[Abstract]=- -This project is part of a Google Summer of Code 2006 project. Many people -have stated that they would like to see improvements in pdb. This projects -aims to fulfill this wish. - --=[TODO]=- -* Write more unit tests -* Write a signal handler that scripts can import from mpdb that, when - the signal is received, start remote debugging. -* info [target/threads] - set debug threads [on|off] - show debug threads, command needs to be written. -* Implement thread debugging, commands to switch between threads. - - Because the 'main' thread may exit unexpectedly we need to keep - any other threads that we're debugging alive. This may mean that - we have to write some code when the main debugger exits to check - for any threads being debugged and not exit until all threads have - finished (or at least ask if they're sure they wanna leave). -* Lightweight and heavyweight mechanism for setting up threads - - The reason we want a lightweight mechanism is so that we can - place mpdb.set_trace() inside a script so that we can debug - the script. It has to be lighweight because the programmer - might not want all the features of an MPdb instance, if for example - they only care about debugging this one thread instance. - - We need a heavyweight mechanism to allow a programmer to inspect - and control all threads. -* Provide a proper top-level methods including, set_trace(), post_mortem(), - run(), remote_sighandler() (for allowing a signal to start - remote debugging) -* Clean up FIFO output (too many newlines) -* mconnection should use the exceptions that have been introduced and mpdb - should check for these exceptions being raised. -* Write documentation - - Debugger commands - - Debugger model/architecture: - - Debugging outside a process - - Debugging remotely - - Debugging threads -* We can switch between threads (like in gdb) with 'thread ', but - this currently has _no_ effect. We should at some point be able to switch - threads and from them on not have to use the 'thread apply ' - syntax, but just '' which would be applied to the current thread. -* Allow reading commands from .mpdbrc file -* Changed the name of the default history file from ~/.pydbhist to ~/.mpdbhist -* do_return inherited from pydb.gdb.Gdb doesn't use self.stdin for reading - input from the user and doesn't work remotely. -* pdbserver using a TCP connection uses setsockopt() REUSEADDR by default. - Need some way to make this configurable. `set reuseaddr' ? -* The style in which mpdb.py is written is too 'amorphous'. Need to at least - separate process, thread and communication code out. - --=[FIXED]=- -* Can restart program remotely with new arguments. -* Allow thread debugging to be turned on with a command line switch. -* Decide on a way to execute commands for a specific thread. ('thread' command) -* Provide a command to distinguish between 'server' and 'client', because - at the moment 'info target' only tells the user whether they are local - or remote, and not whether they are the local/remote server or - local/remote client - target attr is either 'remote-client' or - 'remote-pdbserver'. +-=[Pdb Improvements]=- + +-=[Author: Matt Fleming ]=- +-=[Mentor: Robert L. Bernstein]=- + +-=[Abstract]=- +This project is part of a Google Summer of Code 2006 project. Many people +have stated that they would like to see improvements in pdb. This projects +aims to fulfill this wish. + +-=[TODO]=- +* Write more unit tests +* Write a signal handler that scripts can import from mpdb that, when + the signal is received, start remote debugging. +* info [target/threads] + set debug threads [on|off] + show debug threads, command needs to be written. +* Implement thread debugging, commands to switch between threads. + - Because the 'main' thread may exit unexpectedly we need to keep + any other threads that we're debugging alive. This may mean that + we have to write some code when the main debugger exits to check + for any threads being debugged and not exit until all threads have + finished (or at least ask if they're sure they wanna leave). +* Lightweight and heavyweight mechanism for setting up threads + - The reason we want a lightweight mechanism is so that we can + place mpdb.set_trace() inside a script so that we can debug + the script. It has to be lighweight because the programmer + might not want all the features of an MPdb instance, if for example + they only care about debugging this one thread instance. + - We need a heavyweight mechanism to allow a programmer to inspect + and control all threads. +* Provide a proper top-level methods including, set_trace(), post_mortem(), + run(), remote_sighandler() (for allowing a signal to start + remote debugging) +* Clean up FIFO output (too many newlines) +* mconnection should use the exceptions that have been introduced and mpdb + should check for these exceptions being raised. +* Write documentation + - Debugger commands + - Debugger model/architecture: + - Debugging outside a process + - Debugging remotely + - Debugging threads +* We can switch between threads (like in gdb) with 'thread ', but + this currently has _no_ effect. We should at some point be able to switch + threads and from them on not have to use the 'thread apply ' + syntax, but just '' which would be applied to the current thread. +* Allow reading commands from .mpdbrc file +* Changed the name of the default history file from ~/.pydbhist to ~/.mpdbhist +* do_return inherited from pydb.gdb.Gdb doesn't use self.stdin for reading + input from the user and doesn't work remotely. +* pdbserver using a TCP connection uses setsockopt() REUSEADDR by default. + Need some way to make this configurable. `set reuseaddr' ? +* The style in which mpdb.py is written is too 'amorphous'. Need to at least + separate process, thread and communication code out. + +-=[FIXED]=- +* Can restart program remotely with new arguments. +* Allow thread debugging to be turned on with a command line switch. +* Decide on a way to execute commands for a specific thread. ('thread' command) +* Provide a command to distinguish between 'server' and 'client', because + at the moment 'info target' only tells the user whether they are local + or remote, and not whether they are the local/remote server or + local/remote client - target attr is either 'remote-client' or + 'remote-pdbserver'. Modified: sandbox/trunk/pdb/mconnection.py ============================================================================== --- sandbox/trunk/pdb/mconnection.py (original) +++ sandbox/trunk/pdb/mconnection.py Wed Apr 25 21:51:51 2007 @@ -1,342 +1,342 @@ -""" This file contains all connections that a debugger can -create. -""" - -NotImplementedMessage = "This method must be overriden in a subclass" - -### Exceptions -class ConnectionFailed(Exception): pass -class DroppedConnection(Exception): pass -class ReadError(Exception): pass -class WriteError(Exception): pass - -class MConnectionInterface(object): - """ This is an abstract class that specifies the interface a server - connection class must implement. If a target is given, we'll - set up a connection on that target - """ - def connect(self, target): - """Use this to set the target. It can also be specified - on the initialization.""" - raise NotImplementedError, NotImplementedMessage - - def disconnect(self): - """ This method is called to disconnect connections.""" - raise NotImplementedError, NotImplementedMessage - - def readline(self): - """ This method reads a line of data of maximum length 'bufsize' - from the connected debugger. - """ - raise NotImplementedError, NotImplementedMessage - - def write(self, msg): - """ This method is used to write to a debugger that is - connected to this server. - """ - raise NotImplementedError, NotImplementedMessage - -def import_hook(target): - cls = target[target.rfind('.')+1:] - target = target[:target.rfind('.')] - try: - pkg = __import__(target, globals(), locals(), []) - except ImportError: - return None - return getattr(pkg, cls) - -class MConnectionClientFactory: - - """A factory class that provides a connection for use with a client - for example, with a target function. - """ - @staticmethod - def create(target): - if 'tcp' in target: - return MConnectionClientTCP() - elif 'serial' in target: - return MConnectionSerial() - elif 'fifo' in target: - return MConnectionClientFIFO() - else: - return import_hook(target) - - -class MConnectionServerFactory: - - """A factory class that provides a connection to be used with - a pdbserver. - """ - @staticmethod - def create(target): - if 'tcp' in target: - return MConnectionServerTCP() - elif 'serial' in target: - return MConnectionSerial() - elif 'fifo' in target: - return MConnectionServerFIFO() - else: - return import_hook(target) - -### This might go in a different file -# Not, serial protocol does not require the distinction between server and -# client. -class MConnectionSerial(MConnectionInterface): - - """ This connection class that allows a connection to a - target via a serial line. - """ - - def __init__(self): - MConnectionInterface.__init__(self) - self.input = None - self.output = None - - def connect(self, device): - """ Create our fileobject by opening the serial device for - this connection. A serial device must be specified, - (e.g. /dev/ttyS0, /dev/ttya, COM1, etc.). - """ - self._dev = device - try: - self.input = open(self._dev, 'r') - self.output = open(self._dev, 'w') - except IOError,e: - # Use e[1] for more detail about why the connection failed - raise ConnectionFailed, e[1] - - def disconnect(self): - """ Close the serial device. """ - if self.output is None and self.input is None: - return - self.output.close() - self.input.close() - - def readline(self, bufsize=2048): - try: - line = self.input.readline(bufsize) - except IOError, e: - raise ReadError, e[1] - return line - - def write(self, msg): - if msg[-1] is not '\n': - msg += '\n' - try: - self.output.write(msg) - self.output.flush() - except IOError, e: - raise WriteError, e[1] - - -### This might go in a different file -import socket - -class MConnectionServerTCP(MConnectionInterface): - """This is an implementation of a server class that uses the TCP - protocol as its means of communication. - """ - def __init__(self): - self.listening = False - self._sock = self.output = self.input = None - MConnectionInterface.__init__(self) - - def connect(self, addr, reuseaddr=True): - """Set to allow a connection from a client. 'addr' specifies - the hostname and port combination of the server. - """ - try: - h,p = addr.split(':') - except ValueError: - raise ConnectionFailed, 'Invalid address' - self.host = h - self.port = int(p) - if not self.listening: - self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if reuseaddr: - self._sock.setsockopt(socket.SOL_SOCKET, - socket.SO_REUSEADDR, 1) - try: - self._sock.bind((self.host, self.port)) - except socket.error, e: - # Use e[1] as a more detailed error message - raise ConnectionFailed, e[1] - self._sock.listen(1) - self.listening = True - self.output, addr = self._sock.accept() - self.input = self.output - - def disconnect(self): - if self.output is None or self._sock is None: - return - self.output.close() - self._sock.close() - self._sock = None - self.listening = False - - def readline(self, bufsize=2048): - try: - line = self.input.recv(bufsize) - except socket.error, e: - raise ReadError, e[1] - if not line: - raise ReadError, 'Connection closed' - if line[-1] != '\n': line += '\n' - return line - - def write(self, msg): - try: - self.output.sendall(msg) - except socket.error, e: - raise WriteError, e[1] - -class MConnectionClientTCP(MConnectionInterface): - """ A class that allows a connection to be made from a debugger - to a server via TCP. - """ - def __init__(self): - """ Specify the address to connection to. """ - MConnectionInterface.__init__(self) - self._sock = self.output = self.input = None - self.connected = True - - def connect(self, addr): - """Connect to the server. 'input' reads data from the - server. 'output' writes data to the server. Specify the - address of the server (e.g. host:2020). """ - try: - h, p = addr.split(':') - except ValueError: - raise ConnectionFailed, 'Invalid address' - self.host = h - self.port = int(p) - self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - self._sock.connect((self.host, self.port)) - except socket.error, e: - raise ConnectionFailed, e[1] - self.connected = True - - def write(self, msg): - try: - self._sock.sendall(msg) - except socket.error, e: - raise WriteError, e[1] - - def readline(self, bufsize=2048): - try: - line = self._sock.recv(bufsize) - except socket.error, e: - raise ReadError, e[1] - if not line: - raise ReadError, 'Connection closed' - return line - - def disconnect(self): - """ Close the socket to the server. """ - # We shouldn't bail if we haven't been connected yet - if self._sock is None: - return - else: - self._sock.close() - self._sock = None - self.connected = False - -import os -class MConnectionServerFIFO(MConnectionInterface): - """ This class implements a named pipe for communication between - a pdbserver and client. - """ - def __init__(self): - MConnectionInterface.__init__(self) - self.input = self.output = self._filename = self._mode = None - - def connect(self, name, mode=0644): - self._filename = name - self._file_in = self._filename+'0' - self._file_out = self._filename+'1' - self._mode = mode - try: - os.mkfifo(self._file_in, self._mode) - os.mkfifo(self._file_out, self._mode) - except OSError, e: - raise ConnectionFailed, e[1] - self.input = open(self._file_in, 'r') - self.output = open(self._file_out, 'w') - - def disconnect(self): - """ Disconnect from the named pipe. """ - if not self.input or not self.output: - return - self.output.close() - self.input.close() - self.input = self.output = None - os.unlink(self._file_in) - os.unlink(self._file_out) - - - def readline(self): - """ Read a line from the named pipe. """ - try: - # Using readline allows the data to be read quicker, don't - # know why. - line = self.input.readline() - except IOError, e: - raise ReadError, e[1] - if not line: - raise ReadError, 'Connection closed' - return line - - def write(self, msg): - if msg[-1] != '\n': msg += '\n' - try: - self.output.write(msg) - self.output.flush() - except IOError, e: - raise WriteError, e[1] - -class MConnectionClientFIFO(MConnectionInterface): - """ This class is the client class for accessing a named pipe - used for communication between client and pdbserver. - """ - def __init__(self): - MConnectionInterface.__init__(self) - self.input = self.output = self._filename = self._mode = None - - def connect(self, name, mode=0644): - self._filename = name - self._file_in = self._filename+'1' - self._file_out = self._filename+'0' - self._mode = mode - try: - self.output = open(self._file_out, 'w') - self.input = open(self._file_in, 'r') - except IOError, e: - raise ConnectionFailed, e[1] - - def disconnect(self): - if not self.input or not self.output: - return - self.output.close() - self.input.close() - self.input = self.output = None - - def readline(self): - try: - line = self.input.readline() - except IOError, e: - raise ReadError, e[1] - if not line: - raise ReadError, 'Connection closed' - return line - - def write(self, msg): - if msg[-1] != '\n': msg += '\n' - try: - self.output.write(msg) - self.output.flush() - except IOError, e: - raise WriteError, e[1] - - - +""" This file contains all connections that a debugger can +create. +""" + +NotImplementedMessage = "This method must be overriden in a subclass" + +### Exceptions +class ConnectionFailed(Exception): pass +class DroppedConnection(Exception): pass +class ReadError(Exception): pass +class WriteError(Exception): pass + +class MConnectionInterface(object): + """ This is an abstract class that specifies the interface a server + connection class must implement. If a target is given, we'll + set up a connection on that target + """ + def connect(self, target): + """Use this to set the target. It can also be specified + on the initialization.""" + raise NotImplementedError, NotImplementedMessage + + def disconnect(self): + """ This method is called to disconnect connections.""" + raise NotImplementedError, NotImplementedMessage + + def readline(self): + """ This method reads a line of data of maximum length 'bufsize' + from the connected debugger. + """ + raise NotImplementedError, NotImplementedMessage + + def write(self, msg): + """ This method is used to write to a debugger that is + connected to this server. + """ + raise NotImplementedError, NotImplementedMessage + +def import_hook(target): + cls = target[target.rfind('.')+1:] + target = target[:target.rfind('.')] + try: + pkg = __import__(target, globals(), locals(), []) + except ImportError: + return None + return getattr(pkg, cls) + +class MConnectionClientFactory: + + """A factory class that provides a connection for use with a client + for example, with a target function. + """ + @staticmethod + def create(target): + if 'tcp' in target: + return MConnectionClientTCP() + elif 'serial' in target: + return MConnectionSerial() + elif 'fifo' in target: + return MConnectionClientFIFO() + else: + return import_hook(target) + + +class MConnectionServerFactory: + + """A factory class that provides a connection to be used with + a pdbserver. + """ + @staticmethod + def create(target): + if 'tcp' in target: + return MConnectionServerTCP() + elif 'serial' in target: + return MConnectionSerial() + elif 'fifo' in target: + return MConnectionServerFIFO() + else: + return import_hook(target) + +### This might go in a different file +# Not, serial protocol does not require the distinction between server and +# client. +class MConnectionSerial(MConnectionInterface): + + """ This connection class that allows a connection to a + target via a serial line. + """ + + def __init__(self): + MConnectionInterface.__init__(self) + self.input = None + self.output = None + + def connect(self, device): + """ Create our fileobject by opening the serial device for + this connection. A serial device must be specified, + (e.g. /dev/ttyS0, /dev/ttya, COM1, etc.). + """ + self._dev = device + try: + self.input = open(self._dev, 'r') + self.output = open(self._dev, 'w') + except IOError,e: + # Use e[1] for more detail about why the connection failed + raise ConnectionFailed, e[1] + + def disconnect(self): + """ Close the serial device. """ + if self.output is None and self.input is None: + return + self.output.close() + self.input.close() + + def readline(self, bufsize=2048): + try: + line = self.input.readline(bufsize) + except IOError, e: + raise ReadError, e[1] + return line + + def write(self, msg): + if msg[-1] is not '\n': + msg += '\n' + try: + self.output.write(msg) + self.output.flush() + except IOError, e: + raise WriteError, e[1] + + +### This might go in a different file +import socket + +class MConnectionServerTCP(MConnectionInterface): + """This is an implementation of a server class that uses the TCP + protocol as its means of communication. + """ + def __init__(self): + self.listening = False + self._sock = self.output = self.input = None + MConnectionInterface.__init__(self) + + def connect(self, addr, reuseaddr=True): + """Set to allow a connection from a client. 'addr' specifies + the hostname and port combination of the server. + """ + try: + h,p = addr.split(':') + except ValueError: + raise ConnectionFailed, 'Invalid address' + self.host = h + self.port = int(p) + if not self.listening: + self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if reuseaddr: + self._sock.setsockopt(socket.SOL_SOCKET, + socket.SO_REUSEADDR, 1) + try: + self._sock.bind((self.host, self.port)) + except socket.error, e: + # Use e[1] as a more detailed error message + raise ConnectionFailed, e[1] + self._sock.listen(1) + self.listening = True + self.output, addr = self._sock.accept() + self.input = self.output + + def disconnect(self): + if self.output is None or self._sock is None: + return + self.output.close() + self._sock.close() + self._sock = None + self.listening = False + + def readline(self, bufsize=2048): + try: + line = self.input.recv(bufsize) + except socket.error, e: + raise ReadError, e[1] + if not line: + raise ReadError, 'Connection closed' + if line[-1] != '\n': line += '\n' + return line + + def write(self, msg): + try: + self.output.sendall(msg) + except socket.error, e: + raise WriteError, e[1] + +class MConnectionClientTCP(MConnectionInterface): + """ A class that allows a connection to be made from a debugger + to a server via TCP. + """ + def __init__(self): + """ Specify the address to connection to. """ + MConnectionInterface.__init__(self) + self._sock = self.output = self.input = None + self.connected = True + + def connect(self, addr): + """Connect to the server. 'input' reads data from the + server. 'output' writes data to the server. Specify the + address of the server (e.g. host:2020). """ + try: + h, p = addr.split(':') + except ValueError: + raise ConnectionFailed, 'Invalid address' + self.host = h + self.port = int(p) + self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + self._sock.connect((self.host, self.port)) + except socket.error, e: + raise ConnectionFailed, e[1] + self.connected = True + + def write(self, msg): + try: + self._sock.sendall(msg) + except socket.error, e: + raise WriteError, e[1] + + def readline(self, bufsize=2048): + try: + line = self._sock.recv(bufsize) + except socket.error, e: + raise ReadError, e[1] + if not line: + raise ReadError, 'Connection closed' + return line + + def disconnect(self): + """ Close the socket to the server. """ + # We shouldn't bail if we haven't been connected yet + if self._sock is None: + return + else: + self._sock.close() + self._sock = None + self.connected = False + +import os +class MConnectionServerFIFO(MConnectionInterface): + """ This class implements a named pipe for communication between + a pdbserver and client. + """ + def __init__(self): + MConnectionInterface.__init__(self) + self.input = self.output = self._filename = self._mode = None + + def connect(self, name, mode=0644): + self._filename = name + self._file_in = self._filename+'0' + self._file_out = self._filename+'1' + self._mode = mode + try: + os.mkfifo(self._file_in, self._mode) + os.mkfifo(self._file_out, self._mode) + except OSError, e: + raise ConnectionFailed, e[1] + self.input = open(self._file_in, 'r') + self.output = open(self._file_out, 'w') + + def disconnect(self): + """ Disconnect from the named pipe. """ + if not self.input or not self.output: + return + self.output.close() + self.input.close() + self.input = self.output = None + os.unlink(self._file_in) + os.unlink(self._file_out) + + + def readline(self): + """ Read a line from the named pipe. """ + try: + # Using readline allows the data to be read quicker, don't + # know why. + line = self.input.readline() + except IOError, e: + raise ReadError, e[1] + if not line: + raise ReadError, 'Connection closed' + return line + + def write(self, msg): + if msg[-1] != '\n': msg += '\n' + try: + self.output.write(msg) + self.output.flush() + except IOError, e: + raise WriteError, e[1] + +class MConnectionClientFIFO(MConnectionInterface): + """ This class is the client class for accessing a named pipe + used for communication between client and pdbserver. + """ + def __init__(self): + MConnectionInterface.__init__(self) + self.input = self.output = self._filename = self._mode = None + + def connect(self, name, mode=0644): + self._filename = name + self._file_in = self._filename+'1' + self._file_out = self._filename+'0' + self._mode = mode + try: + self.output = open(self._file_out, 'w') + self.input = open(self._file_in, 'r') + except IOError, e: + raise ConnectionFailed, e[1] + + def disconnect(self): + if not self.input or not self.output: + return + self.output.close() + self.input.close() + self.input = self.output = None + + def readline(self): + try: + line = self.input.readline() + except IOError, e: + raise ReadError, e[1] + if not line: + raise ReadError, 'Connection closed' + return line + + def write(self, msg): + if msg[-1] != '\n': msg += '\n' + try: + self.output.write(msg) + self.output.flush() + except IOError, e: + raise WriteError, e[1] + + + Modified: sandbox/trunk/rjsh-pybench/Empty.py ============================================================================== --- sandbox/trunk/rjsh-pybench/Empty.py (original) +++ sandbox/trunk/rjsh-pybench/Empty.py Wed Apr 25 21:51:51 2007 @@ -1,23 +1,23 @@ -from pybench import Test - -class EmptyTest(Test): - """This is just here as a potential measure of repeatability.""" - - version = 0.3 - operations = 1 - rounds = 60000 - - def test(self): - - l = [] - for i in xrange(self.rounds): - pass - - - def calibrate(self): - - l = [] - - for i in xrange(self.rounds): - pass - +from pybench import Test + +class EmptyTest(Test): + """This is just here as a potential measure of repeatability.""" + + version = 0.3 + operations = 1 + rounds = 60000 + + def test(self): + + l = [] + for i in xrange(self.rounds): + pass + + + def calibrate(self): + + l = [] + + for i in xrange(self.rounds): + pass + Modified: sandbox/trunk/setuptools/setuptools/tests/win_script_wrapper.txt ============================================================================== --- sandbox/trunk/setuptools/setuptools/tests/win_script_wrapper.txt (original) +++ sandbox/trunk/setuptools/setuptools/tests/win_script_wrapper.txt Wed Apr 25 21:51:51 2007 @@ -1,104 +1,104 @@ -Python Script Wrapper for Windows -================================= - -setuptools includes wrappers for Python scripts that allows them to be -executed like regular windows programs. There are 2 wrappers, once -for command-line programs, cli.exe, and one for graphica programs, -gui.exe. These programs are almost identical, function pretty much -the same way, and are generated from the same source file. In this -document, we'll demonstrate use of the command-line program only. The -wrapper programs are used by copying them to the directory containing -the script they are to wrap and with the same name as the script they -are to wrap. In the rest of this document, we'll give an example that -will illustrate this. - -Let's create a simple script, foo-script.py: - - >>> import os, sys, tempfile - >>> from setuptools.command.easy_install import nt_quote_arg - >>> sample_directory = tempfile.mkdtemp() - >>> open(os.path.join(sample_directory, 'foo-script.py'), 'w').write( - ... """#!%(python_exe)s - ... import sys - ... input = repr(sys.stdin.read()) - ... print sys.argv[0][-14:] - ... print sys.argv[1:] - ... print input - ... if __debug__: - ... print 'non-optimized' - ... """ % dict(python_exe=nt_quote_arg(sys.executable))) - -Note that the script starts with a Unix-style '#!' line saying which -Python executable to run. The wrapper will use this to find the -correct Python executable. - -We'll also copy cli.exe to the sample-directory with the name foo.exe: - - >>> import pkg_resources - >>> open(os.path.join(sample_directory, 'foo.exe'), 'wb').write( - ... pkg_resources.resource_string('setuptools', 'cli.exe') - ... ) - -When the copy of cli.exe, foo.exe in this example, runs, it examines -the path name it was run with and computes a Python script path name -by removing the '.exe' suffic and adding the '-script.py' suffix. (For -GUI programs, the suffix '-script-pyw' is added.) This is why we -named out script the way we did. Now we can run out script by running -the wrapper: - - >>> import os - >>> input, output = os.popen4('"'+nt_quote_arg(os.path.join(sample_directory, 'foo.exe')) - ... + r' arg1 "arg 2" "arg \"2\\\"" "arg 4\\" "arg5 a\\b"') - >>> input.write('hello\nworld\n') - >>> input.close() - >>> print output.read(), - \foo-script.py - ['arg1', 'arg 2', 'arg "2\\"', 'arg 4\\', 'arg5 a\\\\b'] - 'hello\nworld\n' - non-optimized - -This example was a little pathological in that it exercised windows -(MS C runtime) quoting rules: - -- Strings containing spaces are surrounded by double quotes. - -- Double quotes in strings need to be escaped by preceding them with - back slashes. - -- One or more backslashes preceding double quotes quotes need to be - escaped by preceding each of them them with back slashes. - -Specifying Python Command-line Options --------------------------------------- - -You can specify a single argument on the '#!' line. This can be used -to specify Python options like -O, to run in optimized mode or -i -to start the interactive interpreter. You can combine multiple -options as usual. For example, to run in optimized mode and -enter the interpreter after running the script, you could use -Oi: - - >>> open(os.path.join(sample_directory, 'foo-script.py'), 'w').write( - ... """#!%(python_exe)s -Oi - ... import sys - ... input = repr(sys.stdin.read()) - ... print sys.argv[0][-14:] - ... print sys.argv[1:] - ... print input - ... if __debug__: - ... print 'non-optimized' - ... sys.ps1 = '---' - ... """ % dict(python_exe=nt_quote_arg(sys.executable))) - - >>> input, output = os.popen4(nt_quote_arg(os.path.join(sample_directory, 'foo.exe'))) - >>> input.close() - >>> print output.read(), - \foo-script.py - [] - '' - --- - - -We're done with the sample_directory: - - >>> import shutil - >>> shutil.rmtree(sample_directory) +Python Script Wrapper for Windows +================================= + +setuptools includes wrappers for Python scripts that allows them to be +executed like regular windows programs. There are 2 wrappers, once +for command-line programs, cli.exe, and one for graphica programs, +gui.exe. These programs are almost identical, function pretty much +the same way, and are generated from the same source file. In this +document, we'll demonstrate use of the command-line program only. The +wrapper programs are used by copying them to the directory containing +the script they are to wrap and with the same name as the script they +are to wrap. In the rest of this document, we'll give an example that +will illustrate this. + +Let's create a simple script, foo-script.py: + + >>> import os, sys, tempfile + >>> from setuptools.command.easy_install import nt_quote_arg + >>> sample_directory = tempfile.mkdtemp() + >>> open(os.path.join(sample_directory, 'foo-script.py'), 'w').write( + ... """#!%(python_exe)s + ... import sys + ... input = repr(sys.stdin.read()) + ... print sys.argv[0][-14:] + ... print sys.argv[1:] + ... print input + ... if __debug__: + ... print 'non-optimized' + ... """ % dict(python_exe=nt_quote_arg(sys.executable))) + +Note that the script starts with a Unix-style '#!' line saying which +Python executable to run. The wrapper will use this to find the +correct Python executable. + +We'll also copy cli.exe to the sample-directory with the name foo.exe: + + >>> import pkg_resources + >>> open(os.path.join(sample_directory, 'foo.exe'), 'wb').write( + ... pkg_resources.resource_string('setuptools', 'cli.exe') + ... ) + +When the copy of cli.exe, foo.exe in this example, runs, it examines +the path name it was run with and computes a Python script path name +by removing the '.exe' suffic and adding the '-script.py' suffix. (For +GUI programs, the suffix '-script-pyw' is added.) This is why we +named out script the way we did. Now we can run out script by running +the wrapper: + + >>> import os + >>> input, output = os.popen4('"'+nt_quote_arg(os.path.join(sample_directory, 'foo.exe')) + ... + r' arg1 "arg 2" "arg \"2\\\"" "arg 4\\" "arg5 a\\b"') + >>> input.write('hello\nworld\n') + >>> input.close() + >>> print output.read(), + \foo-script.py + ['arg1', 'arg 2', 'arg "2\\"', 'arg 4\\', 'arg5 a\\\\b'] + 'hello\nworld\n' + non-optimized + +This example was a little pathological in that it exercised windows +(MS C runtime) quoting rules: + +- Strings containing spaces are surrounded by double quotes. + +- Double quotes in strings need to be escaped by preceding them with + back slashes. + +- One or more backslashes preceding double quotes quotes need to be + escaped by preceding each of them them with back slashes. + +Specifying Python Command-line Options +-------------------------------------- + +You can specify a single argument on the '#!' line. This can be used +to specify Python options like -O, to run in optimized mode or -i +to start the interactive interpreter. You can combine multiple +options as usual. For example, to run in optimized mode and +enter the interpreter after running the script, you could use -Oi: + + >>> open(os.path.join(sample_directory, 'foo-script.py'), 'w').write( + ... """#!%(python_exe)s -Oi + ... import sys + ... input = repr(sys.stdin.read()) + ... print sys.argv[0][-14:] + ... print sys.argv[1:] + ... print input + ... if __debug__: + ... print 'non-optimized' + ... sys.ps1 = '---' + ... """ % dict(python_exe=nt_quote_arg(sys.executable))) + + >>> input, output = os.popen4(nt_quote_arg(os.path.join(sample_directory, 'foo.exe'))) + >>> input.close() + >>> print output.read(), + \foo-script.py + [] + '' + --- + + +We're done with the sample_directory: + + >>> import shutil + >>> shutil.rmtree(sample_directory) From python-checkins at python.org Wed Apr 25 21:57:25 2007 From: python-checkins at python.org (barry.warsaw) Date: Wed, 25 Apr 2007 21:57:25 +0200 (CEST) Subject: [Python-checkins] r54967 - sandbox/trunk/emailpkg/4_0 Message-ID: <20070425195725.C6B221E400C@bag.python.org> Author: barry.warsaw Date: Wed Apr 25 21:57:23 2007 New Revision: 54967 Modified: sandbox/trunk/emailpkg/4_0/ (props changed) Log: more ignores From python-checkins at python.org Wed Apr 25 22:06:15 2007 From: python-checkins at python.org (barry.warsaw) Date: Wed, 25 Apr 2007 22:06:15 +0200 (CEST) Subject: [Python-checkins] r54968 - sandbox/trunk/emailpkg/tags/4_0_2 Message-ID: <20070425200615.58A1E1E4010@bag.python.org> Author: barry.warsaw Date: Wed Apr 25 22:06:14 2007 New Revision: 54968 Added: sandbox/trunk/emailpkg/tags/4_0_2/ - copied from r54967, python/branches/release25-maint/Lib/email/ Log: Tag email package 4.0.2. From python-checkins at python.org Wed Apr 25 22:41:36 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 25 Apr 2007 22:41:36 +0200 (CEST) Subject: [Python-checkins] r54969 - python/trunk/Lib/test/test_ossaudiodev.py Message-ID: <20070425204136.6151A1E400C@bag.python.org> Author: collin.winter Date: Wed Apr 25 22:41:34 2007 New Revision: 54969 Modified: python/trunk/Lib/test/test_ossaudiodev.py Log: Convert test_ossaudiodev to use unittest. Modified: python/trunk/Lib/test/test_ossaudiodev.py ============================================================================== --- python/trunk/Lib/test/test_ossaudiodev.py (original) +++ python/trunk/Lib/test/test_ossaudiodev.py Wed Apr 25 22:41:34 2007 @@ -1,7 +1,7 @@ from test import test_support test_support.requires('audio') -from test.test_support import verbose, findfile, TestFailed, TestSkipped +from test.test_support import verbose, findfile, TestSkipped import errno import fcntl @@ -12,6 +12,7 @@ import sunaudio import time import audioop +import unittest # Arggh, AFMT_S16_NE not defined on all platforms -- seems to be a # fairly recent addition to OSS. @@ -33,131 +34,135 @@ fp.close() if enc != SND_FORMAT_MULAW_8: - print "Expect .au file with 8-bit mu-law samples" - return + raise RuntimeError("Expect .au file with 8-bit mu-law samples") # Convert the data to 16-bit signed. data = audioop.ulaw2lin(data, 2) return (data, rate, 16, nchannels) -# version of assert that still works with -O -def _assert(expr, message=None): - if not expr: - raise AssertionError(message or "assertion failed") - -def play_sound_file(data, rate, ssize, nchannels): - try: - dsp = ossaudiodev.open('w') - except IOError, msg: - if msg[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise TestSkipped, msg - raise TestFailed, msg - - # at least check that these methods can be invoked - dsp.bufsize() - dsp.obufcount() - dsp.obuffree() - dsp.getptr() - dsp.fileno() - - # Make sure the read-only attributes work. - _assert(dsp.closed is False, "dsp.closed is not False") - _assert(dsp.name == "/dev/dsp") - _assert(dsp.mode == 'w', "bad dsp.mode: %r" % dsp.mode) +class OSSAudioDevTests(unittest.TestCase): - # And make sure they're really read-only. - for attr in ('closed', 'name', 'mode'): + def play_sound_file(self, data, rate, ssize, nchannels): try: - setattr(dsp, attr, 42) - raise RuntimeError("dsp.%s not read-only" % attr) - except TypeError: - pass - - # Compute expected running time of sound sample (in seconds). - expected_time = float(len(data)) / (ssize/8) / nchannels / rate - - # set parameters based on .au file headers - dsp.setparameters(AFMT_S16_NE, nchannels, rate) - print ("playing test sound file (expected running time: %.2f sec)" - % expected_time) - t1 = time.time() - dsp.write(data) - dsp.close() - t2 = time.time() - elapsed_time = t2 - t1 - - percent_diff = (abs(elapsed_time - expected_time) / expected_time) * 100 - _assert(percent_diff <= 10.0, \ - ("elapsed time (%.2f sec) > 10%% off of expected time (%.2f sec)" - % (elapsed_time, expected_time))) - -def test_setparameters(dsp): - # Two configurations for testing: - # config1 (8-bit, mono, 8 kHz) should work on even the most - # ancient and crufty sound card, but maybe not on special- - # purpose high-end hardware - # config2 (16-bit, stereo, 44.1kHz) should work on all but the - # most ancient and crufty hardware - config1 = (ossaudiodev.AFMT_U8, 1, 8000) - config2 = (AFMT_S16_NE, 2, 44100) - - for config in [config1, config2]: - (fmt, channels, rate) = config - if (dsp.setfmt(fmt) == fmt and - dsp.channels(channels) == channels and - dsp.speed(rate) == rate): - break - else: - raise RuntimeError("unable to set audio sampling parameters: " - "you must have really weird audio hardware") + dsp = ossaudiodev.open('w') + except IOError, msg: + if msg[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): + raise TestSkipped(msg) + raise + + # at least check that these methods can be invoked + dsp.bufsize() + dsp.obufcount() + dsp.obuffree() + dsp.getptr() + dsp.fileno() + + # Make sure the read-only attributes work. + self.failUnless(dsp.close) + self.assertEqual(dsp.name, "/dev/dsp") + self.assertEqual(dsp.mode, "w", "bad dsp.mode: %r" % dsp.mode) + + # And make sure they're really read-only. + for attr in ('closed', 'name', 'mode'): + try: + setattr(dsp, attr, 42) + except TypeError: + pass + else: + self.fail("dsp.%s not read-only" % attr) + + # Compute expected running time of sound sample (in seconds). + expected_time = float(len(data)) / (ssize/8) / nchannels / rate + + # set parameters based on .au file headers + dsp.setparameters(AFMT_S16_NE, nchannels, rate) + print ("playing test sound file (expected running time: %.2f sec)" + % expected_time) + t1 = time.time() + dsp.write(data) + dsp.close() + t2 = time.time() + elapsed_time = t2 - t1 - # setparameters() should be able to set this configuration in - # either strict or non-strict mode. - result = dsp.setparameters(fmt, channels, rate, False) - _assert(result == (fmt, channels, rate), - "setparameters%r: returned %r" % (config, result)) - result = dsp.setparameters(fmt, channels, rate, True) - _assert(result == (fmt, channels, rate), - "setparameters%r: returned %r" % (config, result)) - -def test_bad_setparameters(dsp): - - # Now try some configurations that are presumably bogus: eg. 300 - # channels currently exceeds even Hollywood's ambitions, and - # negative sampling rate is utter nonsense. setparameters() should - # accept these in non-strict mode, returning something other than - # was requested, but should barf in strict mode. - fmt = AFMT_S16_NE - rate = 44100 - channels = 2 - for config in [(fmt, 300, rate), # ridiculous nchannels - (fmt, -5, rate), # impossible nchannels - (fmt, channels, -50), # impossible rate - ]: - (fmt, channels, rate) = config + percent_diff = (abs(elapsed_time - expected_time) / expected_time) * 100 + self.failUnless(percent_diff <= 10.0, + "elapsed time > 10% off of expected time") + + def set_parameters(self, dsp): + # Two configurations for testing: + # config1 (8-bit, mono, 8 kHz) should work on even the most + # ancient and crufty sound card, but maybe not on special- + # purpose high-end hardware + # config2 (16-bit, stereo, 44.1kHz) should work on all but the + # most ancient and crufty hardware + config1 = (ossaudiodev.AFMT_U8, 1, 8000) + config2 = (AFMT_S16_NE, 2, 44100) + + for config in [config1, config2]: + (fmt, channels, rate) = config + if (dsp.setfmt(fmt) == fmt and + dsp.channels(channels) == channels and + dsp.speed(rate) == rate): + break + else: + raise RuntimeError("unable to set audio sampling parameters: " + "you must have really weird audio hardware") + + # setparameters() should be able to set this configuration in + # either strict or non-strict mode. result = dsp.setparameters(fmt, channels, rate, False) - _assert(result != config, - "setparameters: unexpectedly got requested configuration") + self.assertEqual(result, (fmt, channels, rate), + "setparameters%r: returned %r" % (config, result)) + + result = dsp.setparameters(fmt, channels, rate, True) + self.assertEqual(result, (fmt, channels, rate), + "setparameters%r: returned %r" % (config, result)) + + def set_bad_parameters(self, dsp): + + # Now try some configurations that are presumably bogus: eg. 300 + # channels currently exceeds even Hollywood's ambitions, and + # negative sampling rate is utter nonsense. setparameters() should + # accept these in non-strict mode, returning something other than + # was requested, but should barf in strict mode. + fmt = AFMT_S16_NE + rate = 44100 + channels = 2 + for config in [(fmt, 300, rate), # ridiculous nchannels + (fmt, -5, rate), # impossible nchannels + (fmt, channels, -50), # impossible rate + ]: + (fmt, channels, rate) = config + result = dsp.setparameters(fmt, channels, rate, False) + self.failIfEqual(result, config, + "unexpectedly got requested configuration") + + try: + result = dsp.setparameters(fmt, channels, rate, True) + except ossaudiodev.OSSAudioError, err: + pass + else: + self.fail("expected OSSAudioError") + + def test_playback(self): + sound_info = read_sound_file(findfile('audiotest.au')) + self.play_sound_file(*sound_info) + def test_set_parameters(self): + dsp = ossaudiodev.open("w") try: - result = dsp.setparameters(fmt, channels, rate, True) - raise AssertionError("setparameters: expected OSSAudioError") - except ossaudiodev.OSSAudioError, err: - print "setparameters: got OSSAudioError as expected" - -def test(): - (data, rate, ssize, nchannels) = read_sound_file(findfile('audiotest.au')) - play_sound_file(data, rate, ssize, nchannels) - - dsp = ossaudiodev.open("w") - try: - test_setparameters(dsp) - - # Disabled because it fails under Linux 2.6 with ALSA's OSS - # emulation layer. - #test_bad_setparameters(dsp) - finally: - dsp.close() - _assert(dsp.closed is True, "dsp.closed is not True") + self.set_parameters(dsp) + + # Disabled because it fails under Linux 2.6 with ALSA's OSS + # emulation layer. + #self.set_bad_parameters(dsp) + finally: + dsp.close() + self.failUnless(dsp.closed) + + +def test_main(): + test_support.run_unittest(__name__) -test() +if __name__ == "__main__": + test_main() From python-checkins at python.org Wed Apr 25 22:43:01 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 25 Apr 2007 22:43:01 +0200 (CEST) Subject: [Python-checkins] r54970 - peps/trunk/pep-0000.txt peps/trunk/pep-3141.txt Message-ID: <20070425204301.1B43A1E400C@bag.python.org> Author: guido.van.rossum Date: Wed Apr 25 22:42:59 2007 New Revision: 54970 Added: peps/trunk/pep-3141.txt (contents, props changed) Modified: peps/trunk/pep-0000.txt Log: Add PEP 3141 (named after 3.141), ABCs for numbers, by Jeffrey Jasskin. Not to endorse this (yet) but so we have a record in svn. Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Wed Apr 25 22:42:59 2007 @@ -117,6 +117,7 @@ S 3117 Postfix Type Declarations Brandl S 3118 Revising the buffer protocol Oliphant, Banks S 3119 Introducing Abstract Base Classes GvR, Talin + S 3141 A Type Hierarchy for Numbers Yasskin Finished PEPs (done, implemented in Subversion) @@ -473,6 +474,7 @@ S 3117 Postfix Type Declarations Brandl S 3118 Revising the buffer protocol Oliphant, Banks S 3119 Introducing Abstract Base Classes GvR, Talin + S 3141 A Type Hierarchy for Numbers Yasskin Key Added: peps/trunk/pep-3141.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-3141.txt Wed Apr 25 22:42:59 2007 @@ -0,0 +1,481 @@ +PEP: 3141 +Title: A Type Hierarchy for Numbers (and other algebraic entities) +Version: $Revision$ +Last-Modified: $Date$ +Author: Jeffrey Yasskin +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 23-Apr-2007 +Post-History: Not yet posted + + +Abstract +======== + +This proposal defines a hierarchy of Abstract Base Classes (ABCs) +[#pep3119] to represent numbers and other algebraic entities similar +to numbers. It proposes: + +* A hierarchy of algebraic concepts, including monoids, groups, rings, + and fields with successively more operators and constraints on their + operators. This will be added as a new library module named + "algebra". + +* A hierarchy of specifically numeric types, which can be converted to + and from the native Python types. This will be added as a new + library module named "numbers". + +Rationale +========= + +Functions that take numbers as arguments should be able to determine +the properties of those numbers, and if and when overloading based on +types is added to the language, should be overloadable based on the +types of the arguments. This PEP defines some abstract base classes +that are useful in numerical calculations. A function can check that +variable is an instance of one of these classes and then rely on the +properties specified for them. Of course, the language cannot check +these properties, so where I say something is "guaranteed", I really +just mean that it's one of those properties a user should be able to +rely on. + +This PEP tries to find a balance between providing fine-grained +distinctions and specifying types that few people will ever use. + +Specification +============= + +Although this PEP uses terminology from PEP 3119, the hierarchy is +meaningful for any systematic method of defining sets of +classes. **Todo:** link to the Interfaces PEP when it's ready. I'm +also using the extra notation from [#pep3107] (annotations) to specify +some types. + +Object oriented systems have a general problem in constraining +functions that take two arguments. To take addition as an example, +``int(3) + int(4)`` is defined, and ``vector(1,2,3) + vector(3,4,5)`` +is defined, but ``int(3) + vector(3,4,5)`` doesn't make much sense. So +``a + b`` is not guaranteed to be defined for any two instances of +``AdditiveGroup``, but it is guaranteed to be defined when ``type(a) +== type(b)``. On the other hand, ``+`` does make sense for any sorts +of numbers, so the ``Complex`` ABC refines the properties for plus so +that ``a + b`` is defined whenever ``isinstance(a,Complex) and +isinstance(b,Complex)``, even if ``type(a) != type(b)``. + + +Monoids (http://en.wikipedia.org/wiki/Monoid) consist of a set with an +associative operation, and an identity element under that +operation. **Open issue**: Is a @classmethod the best way to define +constants that depend only on the type?:: + + class MonoidUnderPlus(Abstract): + """+ is associative but not necessarily commutative and has an + identity given by plus_identity(). + + Subclasses follow the laws: + + a + (b + c) === (a + b) + c + a.plus_identity() + a === a === a + a.plus_identity() + + Sequences are monoids under plus (in Python) but are not + AdditiveGroups. + """ + @abstractmethod + def __add__(self, other): + raise NotImplementedError + + @classmethod + @abstractmethod + def plus_identity(cls): + raise NotImplementedError + +I skip ordinary non-commutative groups here because I don't have any +common examples of groups that use ``+`` as their operator but aren't +commutative. If we find some, the class can be added later.:: + + class AdditiveGroup(MonoidUnderPlus): + """Defines a commutative group whose operator is +, and whose inverses + are produced by -x. + See http://en.wikipedia.org/wiki/Abelian_group. + + Where a, b, and c are instances of the same subclass of + AdditiveGroup, the operations should follow these laws, where + 'zero' is a.__class__.zero(). + + a + b === b + a + (a + b) + c === a + (b + c) + zero + a === a + a + (-a) === zero + a - b === a + -b + + Some abstract subclasses, such as Complex, may extend the + definition of + to heterogenous subclasses, but AdditiveGroup only + guarantees it's defined on arguments of exactly the same types. + + Vectors are AdditiveGroups but are not Rings. + """ + @abstractmethod + def __add__(self, other): + """Associative commutative operation, whose inverse is negation.""" + raise NotImplementedError + + # **Open issue:** Do we want to give people a choice of which of the + # following to define, or should we pick one arbitrarily?:: + + def __neg__(self): + """Must define this or __sub__().""" + return self.zero() - self + + def __sub__(self, other): + """Must define this or __neg__().""" + return self + -other + + @classmethod + @abstractmethod + def zero(cls): + """A better name for +'s identity as we move into more mathematical + domains.""" + raise NotImplementedError + + @classmethod + def plus_identity(cls): + return cls.zero() + +Including Semiring (http://en.wikipedia.org/wiki/Semiring) would help +a little with defining a type for the natural numbers. That can be +split out once someone needs it (see ``IntegralDomain`` for how).:: + + class Ring(AdditiveGroup): + """A mathematical ring over the operations + and *. + See http://en.wikipedia.org/wiki/Ring_%28mathematics%29. + + In addition to the requirements of the AdditiveGroup superclass, a + Ring has an associative but not necessarily commutative + multiplication operation with identity (one) that distributes over + addition. A Ring can be constructed from any integer 'i' by adding + 'one' to itself 'i' times. When R is a subclass of Ring, the + additive identity is R(0), and the multiplicative identity is + R(1). + + Matrices are Rings but not Commutative Rings or Division + Rings. The quaternions are a Division Ring but not a + Field. The integers are a Commutative Ring but not a Field. + """ + @abstractmethod + def __init__(self, i:int): + """An instance of a Ring may be constructed from an integer. + + This may be a lossy conversion, as in the case of the integers + modulo N.""" + pass + + @abstractmethod + def __mul__(self, other): + """Satisfies: + a * (b * c) === (a * b) * c + one * a === a + a * one === a + a * (b + c) === a * b + a * c + + where one == a.__class__(1) + """ + raise NotImplementedError + + @classmethod + def zero(cls): + return cls(0) + + @classmethod + def one(cls): + return cls(1) + +I'm skipping both CommutativeRing and DivisionRing here.:: + + class Field(Ring): + """The class Field adds to Ring the requirement that * be a + commutative group operation except that zero does not have an + inverse. + See http://en.wikipedia.org/wiki/Field_%28mathematics%29. + + Practically, that means we can define division on a Field. The + additional laws are: + + a * b === b * a + a / a === a.__class_(1) # when a != a.__class__(0) + + Division lets us construct a Field from any Python float, + although the conversion is likely to be lossy. Some Fields + include the real numbers, rationals, and integers mod a + prime. Python's ``float`` resembles a Field closely. + """ + def __init__(self, f:float): + """A Field should be constructible from any rational number, which + includes Python floats.""" + pass + + @abstractmethod + def __div__(self, divisor): + raise NotImplementedError + +Division is somewhat complicated in Python. You have both __floordiv__ +and __div__, and ints produce floats when they're divided. For the +purposes of this hierarchy, ``__floordiv__(a, b)`` is defined by +``floor(__div__(a, b))``, and, since int is not a subclass of Field, +it's allowed to do whatever it wants with __div__. + +There are four more reasonable classes that I'm skipping here in the +interest of keeping the initial library simple. They are: + +``Algebraic`` + Rational powers of its elements are defined (and maybe a few other + operations) + (http://en.wikipedia.org/wiki/Algebraic_number). Complex numbers + are the most well-known algebraic set. Real numbers are _not_ + algebraic, but Python does define these operations on floats, + which makes defining this class somewhat difficult. + +``Trancendental`` + The elementary functions + (http://en.wikipedia.org/wiki/Elementary_function) are + defined. These are basically arbitrary powers, trig functions, and + logs, the contents of ``cmath``. + +The following two classes can be reasonably combined with ``Integral`` +for now. + +``IntegralDomain`` + Defines __divmod__. + (http://darcs.haskell.org/numericprelude/docs/html/Algebra-IntegralDomain.html#t%3AC) + +``PrincipalIdealDomain`` + Defines gcd and lcm. + (http://darcs.haskell.org/numericprelude/docs/html/Algebra-PrincipalIdealDomain.html#t%3AC) + +If someone needs to split them later, they can use code like:: + import numbers + class IntegralDomain(Ring): ... + numbers.Integral.__bases__ = (IntegralDomain,) + numbers.Integral.__bases__ + + +Finally, we get to numbers. This is where we switch from the "algebra" +module to the "numbers" module.:: + + class Complex(Ring, Hashable): + """The ``Complex`` ABC indicates that the value lies somewhere + on the complex plane, not that it in fact has a complex + component: ``int`` is a subclass of ``Complex``. Because these + actually represent complex numbers, they can be converted to + the ``complex`` type. + + ``Complex`` finally gets around to requiring its subtypes to + be immutable so they can be hashed in a standard way. + + ``Complex`` also requires its operations to accept + heterogenous arguments. Subclasses should override the + operators to be more accurate when they can, but should fall + back on the default definitions to handle arguments of + different (Complex) types. + + **Open issue:** __abs__ doesn't fit here because it doesn't + exist for the Gaussian integers + (http://en.wikipedia.org/wiki/Gaussian_integer). In fact, it + only exists for algebraic complex numbers and real numbers. We + could define it in both places, or leave it out of the + ``Complex`` classes entirely and let it be a custom extention + of the ``complex`` type. + + The Gaussian integers are ``Complex`` but not a ``Field``. + """ + @abstractmethod + def __complex__(self): + """Any Complex can be converted to a native complex object.""" + raise NotImplementedError + + def __hash__(self): + return hash(complex(self)) + + @abstractmethod + def real(self) => Real: + raise NotImplementedError + + @abstractmethod + def imag(self) => Real: + raise NotImplementedError + + @abstractmethod + def __add__(self, other): + """The other Ring operations should be implemented similarly.""" + if isinstance(other, Complex): + return complex(self) + complex(other) + else: + return NotImplemented + +``FractionalComplex(Complex, Field)`` might fit here, except that it +wouldn't give us any new operations.:: + + class Real(Complex, TotallyOrdered): + """Numbers along the real line. Some subclasses of this class + may contain NaNs that are not ordered with the rest of the + instances of that type. Oh well. **Open issue:** what problems + will that cause? Is it worth it in order to get a + straightforward type hierarchy? + """ + @abstractmethod + def __float__(self): + raise NotImplementedError + def __complex__(self): + return complex(float(self)) + def real(self) => self.__class__: + return self + def imag(self) => self.__class__: + return self.__class__(0) + def __abs__(self) => self.__class__: + if self < 0: return -self + else: return self + + + class FractionalReal(Real, Field): + """Rationals and floats. This class provides concrete + definitions of the other four methods from properfraction and + allows you to convert fractional reals to integers in a + disciplined way. + """ + @abstractmethod + def properfraction(self) => (int, self.__class__): + """Returns a pair (n,f) such that self == n+f, and: + * n is an integral number with the same sign as self; and + * f is a fraction with the same type and sign as self, and with + absolute value less than 1. + """ + raise NotImplementedError + def floor(self) => int: + n, r = self.properfraction() + if r < 0 then n - 1 else n + def ceiling(self) => int: ... + def __trunc__(self) => int: ... + def round(self) => int: ... + + +**Open issue:** What's the best name for this class? RealIntegral? Integer?:: + + class Integral(Real): + """Integers!""" + @abstractmethod + def __int__(self): + raise NotImplementedError + def __float__(self): + return float(int(self)) + + @abstractmethod + def __or__(self, other): + raise NotImplementedError + @abstractmethod + def __xor__(self, other): + raise NotImplementedError + @abstractmethod + def __and__(self, other): + raise NotImplementedError + @abstractmethod + def __lshift__(self, other): + raise NotImplementedError + @abstractmethod + def __rshift__(self, other): + raise NotImplementedError + @abstractmethod + def __invert__(self): + raise NotImplementedError + + +Floating point values may not exactly obey several of the properties +you would expect from their superclasses. For example, it is possible +for ``(large_val + -large_val) + 3 == 3``, but ``large_val + +(-large_val + 3) == 0``. On the values most functions deal with this +isn't a problem, but it is something to be aware of. Types like this +inherit from ``FloatingReal`` so that functions that care can know to +use a numerically stable algorithm on them. **Open issue:** Is this +the proper way to handle floating types?:: + + class FloatingReal: + """A "floating" number is one that is represented as + ``mantissa * radix**exponent`` where mantissa, radix, and + exponent are all integers. Subclasses of FloatingReal don't + follow all the rules you'd expect numbers to follow. If you + really care about the answer, you have to use numerically + stable algorithms, whatever those are. + + **Open issue:** What other operations would be useful here? + + These include floats and Decimals. + """ + @classmethod + @abstractmethod + def radix(cls) => int: + raise NotImplementedError + + @classmethod + @abstractmethod + def digits(cls) => int: + """The number of significant digits of base cls.radix().""" + raise NotImplementedError + + @classmethod + @abstractmethod + def exponentRange(cls) => (int, int): + """A pair of the (lowest,highest) values possible in the exponent.""" + raise NotImplementedError + + @abstractmethod + def decode(self) => (int, int): + """Returns a pair (mantissa, exponent) such that + mantissa*self.radix()**exponent == self.""" + raise NotImplementedError + + + +Inspiration +=========== +http://hackage.haskell.org/trac/haskell-prime/wiki/StandardClasses +http://repetae.net/john/recent/out/classalias.html + +References +========== + +.. [#pep3119] Introducing Abstract Base Classes + (http://www.python.org/dev/peps/pep-3119/) + +.. [#pep3107] Function Annotations + (http://www.python.org/dev/peps/pep-3107/) + +.. [3] Possible Python 3K Class Tree?, wiki page created by Bill Janssen + (http://wiki.python.org/moin/AbstractBaseClasses) + +.. [#numericprelude] NumericPrelude: An experimental alternative + hierarchy of numeric type classes + (http://darcs.haskell.org/numericprelude/docs/html/index.html) + + +Acknowledgements +---------------- + +Thanks to Neil Norwitz for helping me through the PEP process. + +The Haskell Numeric Prelude [#numericprelude] nicely condensed a lot +of experience with the Haskell numeric hierarchy into a form that was +relatively easily adaptable to Python. + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: From python-checkins at python.org Wed Apr 25 22:45:46 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 25 Apr 2007 22:45:46 +0200 (CEST) Subject: [Python-checkins] r54971 - peps/trunk/pep-3141.txt Message-ID: <20070425204546.5ADBF1E400C@bag.python.org> Author: guido.van.rossum Date: Wed Apr 25 22:45:43 2007 New Revision: 54971 Modified: peps/trunk/pep-3141.txt Log: Tiny formatting tweak. Modified: peps/trunk/pep-3141.txt ============================================================================== --- peps/trunk/pep-3141.txt (original) +++ peps/trunk/pep-3141.txt Wed Apr 25 22:45:43 2007 @@ -120,8 +120,10 @@ """Associative commutative operation, whose inverse is negation.""" raise NotImplementedError - # **Open issue:** Do we want to give people a choice of which of the - # following to define, or should we pick one arbitrarily?:: +**Open issue:** Do we want to give people a choice of which of the +following to define, or should we pick one arbitrarily?:: + + # AdditiveGroup, continued def __neg__(self): """Must define this or __sub__().""" From python-checkins at python.org Wed Apr 25 23:05:32 2007 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 25 Apr 2007 23:05:32 +0200 (CEST) Subject: [Python-checkins] r54972 - peps/trunk/pep-3119.txt peps/trunk/pep-3141.txt Message-ID: <20070425210532.EF39A1E4012@bag.python.org> Author: guido.van.rossum Date: Wed Apr 25 23:05:21 2007 New Revision: 54972 Modified: peps/trunk/pep-3119.txt peps/trunk/pep-3141.txt Log: Fix up references in PEP 3141. Point PEP 3119 to PEP 3141. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Wed Apr 25 23:05:21 2007 @@ -547,10 +547,7 @@ ABCs for Numbers ---------------- -**Open issues:** Define: ``Number``, ``Complex``, ``Real``, -``Rational``, ``Integer``. Maybe also ``Cardinal`` (``Integer`` >= -0)? We probably also need ``Index``, which converts to ``Integer`` -using ``__index__``. This should be moved out to a separate PEP. +ABCs for numerical types are defined in PEP 3141. Guidelines for Writing ABCs Modified: peps/trunk/pep-3141.txt ============================================================================== --- peps/trunk/pep-3141.txt (original) +++ peps/trunk/pep-3141.txt Wed Apr 25 23:05:21 2007 @@ -13,9 +13,9 @@ Abstract ======== -This proposal defines a hierarchy of Abstract Base Classes (ABCs) -[#pep3119] to represent numbers and other algebraic entities similar -to numbers. It proposes: +This proposal defines a hierarchy of Abstract Base Classes (ABCs) (see +PEP 3119) to represent numbers and other algebraic entities similar to +numbers. It proposes: * A hierarchy of algebraic concepts, including monoids, groups, rings, and fields with successively more operators and constraints on their @@ -49,7 +49,7 @@ Although this PEP uses terminology from PEP 3119, the hierarchy is meaningful for any systematic method of defining sets of classes. **Todo:** link to the Interfaces PEP when it's ready. I'm -also using the extra notation from [#pep3107] (annotations) to specify +also using the extra notation from PEP 3107 (annotations) to specify some types. Object oriented systems have a general problem in constraining @@ -443,16 +443,16 @@ References ========== -.. [#pep3119] Introducing Abstract Base Classes +.. [1] Introducing Abstract Base Classes (http://www.python.org/dev/peps/pep-3119/) -.. [#pep3107] Function Annotations +.. [2] Function Annotations (http://www.python.org/dev/peps/pep-3107/) .. [3] Possible Python 3K Class Tree?, wiki page created by Bill Janssen (http://wiki.python.org/moin/AbstractBaseClasses) -.. [#numericprelude] NumericPrelude: An experimental alternative +.. [4] NumericPrelude: An experimental alternative hierarchy of numeric type classes (http://darcs.haskell.org/numericprelude/docs/html/index.html) @@ -462,7 +462,7 @@ Thanks to Neil Norwitz for helping me through the PEP process. -The Haskell Numeric Prelude [#numericprelude] nicely condensed a lot +The Haskell Numeric Prelude [4]_ nicely condensed a lot of experience with the Haskell numeric hierarchy into a form that was relatively easily adaptable to Python. From buildbot at python.org Wed Apr 25 23:05:36 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 21:05:36 +0000 Subject: [Python-checkins] buildbot warnings in amd64 gentoo trunk Message-ID: <20070425210536.5BD891E400F@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%2520gentoo%2520trunk/builds/1981 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_ossaudiodev ====================================================================== ERROR: test_playback (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_ossaudiodev.py", line 149, in test_playback self.play_sound_file(*sound_info) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_ossaudiodev.py", line 50, in play_sound_file raise TestSkipped(msg) TestSkipped: [Errno 13] Permission denied: '/dev/dsp' ====================================================================== ERROR: test_set_parameters (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_ossaudiodev.py", line 152, in test_set_parameters dsp = ossaudiodev.open("w") IOError: [Errno 13] Permission denied: '/dev/dsp' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Apr 25 23:06:01 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 21:06:01 +0000 Subject: [Python-checkins] buildbot warnings in x86 mvlgcc trunk Message-ID: <20070425210601.B9AEE1E4013@bag.python.org> The Buildbot has detected a new failure of x86 mvlgcc trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520mvlgcc%2520trunk/builds/488 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_ossaudiodev ====================================================================== ERROR: test_playback (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_ossaudiodev.py", line 149, in test_playback self.play_sound_file(*sound_info) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_ossaudiodev.py", line 50, in play_sound_file raise TestSkipped(msg) TestSkipped: [Errno 2] No such file or directory: '/dev/dsp' ====================================================================== ERROR: test_set_parameters (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/test/test_ossaudiodev.py", line 152, in test_set_parameters dsp = ossaudiodev.open("w") IOError: [Errno 2] No such file or directory: '/dev/dsp' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Apr 25 23:07:26 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 21:07:26 +0000 Subject: [Python-checkins] buildbot warnings in x86 gentoo trunk Message-ID: <20070425210727.175801E4015@bag.python.org> The Buildbot has detected a new failure of x86 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520gentoo%2520trunk/builds/2164 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_ossaudiodev ====================================================================== ERROR: test_playback (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_ossaudiodev.py", line 149, in test_playback self.play_sound_file(*sound_info) File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_ossaudiodev.py", line 50, in play_sound_file raise TestSkipped(msg) TestSkipped: [Errno 2] No such file or directory: '/dev/dsp' ====================================================================== ERROR: test_set_parameters (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_ossaudiodev.py", line 152, in test_set_parameters dsp = ossaudiodev.open("w") IOError: [Errno 2] No such file or directory: '/dev/dsp' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Apr 25 23:09:03 2007 From: python-checkins at python.org (facundo.batista) Date: Wed, 25 Apr 2007 23:09:03 +0200 (CEST) Subject: [Python-checkins] r54973 - python/branches/decimal-branch/Lib/decimal.py Message-ID: <20070425210903.C71FE1E400F@bag.python.org> Author: facundo.batista Date: Wed Apr 25 23:08:57 2007 New Revision: 54973 Modified: python/branches/decimal-branch/Lib/decimal.py Log: Fixed all the NaN and Inf cases, in all its variants. It does not passes all the integer-rhs tests, though, there's one strange case with an out-of-range exponent (?) Modified: python/branches/decimal-branch/Lib/decimal.py ============================================================================== --- python/branches/decimal-branch/Lib/decimal.py (original) +++ python/branches/decimal-branch/Lib/decimal.py Wed Apr 25 23:08:57 2007 @@ -1790,7 +1790,7 @@ else: return self._round_up(prec, expdiff, context) - def __pow__(self, n, modulo = None, context=None): + def __pow__(self, n, modulo=None, context=None): """Return self ** n (mod modulo) If modulo is None (default), don't take it mod modulo. @@ -1802,37 +1802,96 @@ if context is None: context = getcontext() - if self._is_special or n._is_special or n.adjusted() > 8: - # Because the spot << doesn't work with really big exponents - if n._isinfinity() or n.adjusted() > 8: - return context._raise_error(InvalidOperation, 'x ** INF') +# # FIXME: study if this finally disappears... +# if self._is_special or n._is_special:# or n.adjusted() > 8: +# # Because the spot << doesn't work with really big exponents +# if n._isinfinity() or n.adjusted() > 8: +# return context._raise_error(InvalidOperation, 'x ** INF') - ans = self._check_nans(n, context) - if ans: - return ans - - if not n._isinteger(): - return context._raise_error(InvalidOperation, 'x ** (non-integer)') + ans = self._check_nans(n, context) + if ans: + return ans - if not self and not n: - return context._raise_error(InvalidOperation, '0 ** 0') + if not self: + if not n: + return context._raise_error(InvalidOperation, '0 ** 0') + if n._sign == 0: + zero = Decimal(0) + if n._iseven(): + return zero + zero._sign = self._sign + return zero + # n is negative + if self._sign == 0: + return Inf + # also self is negative + if n._iseven(): + return Inf + else: + return negInf if not n: return Decimal(1) + # FIXME: Reduce the following to something more readable if self == Decimal(1): + if n._isinfinity(): + context._raise_error(Inexact) + context._raise_error(Rounded) + digits = (1,)+(0,)*(context.prec-1) + return Decimal((0, digits, -context.prec+1)) return Decimal(1) - sign = self._sign and not n._iseven() - n = int(n) - - if self._isinfinity(): + if self._isinfinity() == -1 and n._isinfinity(): + return context._raise_error(InvalidOperation, '-Inf ** +-Inf') + if self._isinfinity() == 1: + if n._isinfinity() == 1: + return Inf + if n._isinfinity() == -1: + return Decimal(0) + + if self._isinfinity() == 1: if modulo: return context._raise_error(InvalidOperation, 'INF % x') - if n > 0: - return Infsign[sign] - return Decimal( (sign, (0,), 0) ) + if not n: + return Decimal(1) + if n._sign == 1: + return Decimal(0) + return Inf + if self._isinfinity() == -1: + if modulo: + return context._raise_error(InvalidOperation, '-INF % x') + if not n: + return Decimal(1) + if abs(n) < 1: + return context._raise_error(InvalidOperation, '-INF ** -1 1: + return Decimal(0) + else: + return Inf + + sign = self._sign and not n._iseven() + n = int(n) # With ludicrously large exponent, just raise an overflow # and return inf. if not modulo and n > 0 and \ From buildbot at python.org Wed Apr 25 23:34:06 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 21:34:06 +0000 Subject: [Python-checkins] buildbot warnings in ia64 Ubuntu trunk trunk Message-ID: <20070425213406.4BDDA1E4019@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%2520Ubuntu%2520trunk%2520trunk/builds/607 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_ossaudiodev ====================================================================== ERROR: test_playback (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_ossaudiodev.py", line 149, in test_playback self.play_sound_file(*sound_info) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_ossaudiodev.py", line 50, in play_sound_file raise TestSkipped(msg) TestSkipped: [Errno 13] Permission denied: '/dev/dsp' ====================================================================== ERROR: test_set_parameters (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_ossaudiodev.py", line 152, in test_set_parameters dsp = ossaudiodev.open("w") IOError: [Errno 13] Permission denied: '/dev/dsp' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Apr 25 23:50:29 2007 From: python-checkins at python.org (collin.winter) Date: Wed, 25 Apr 2007 23:50:29 +0200 (CEST) Subject: [Python-checkins] r54974 - python/trunk/Lib/test/test_ossaudiodev.py Message-ID: <20070425215029.837C71E400E@bag.python.org> Author: collin.winter Date: Wed Apr 25 23:50:25 2007 New Revision: 54974 Modified: python/trunk/Lib/test/test_ossaudiodev.py Log: Fix an issue related to the unittest conversion. Modified: python/trunk/Lib/test/test_ossaudiodev.py ============================================================================== --- python/trunk/Lib/test/test_ossaudiodev.py (original) +++ python/trunk/Lib/test/test_ossaudiodev.py Wed Apr 25 23:50:25 2007 @@ -162,6 +162,12 @@ def test_main(): + try: + dsp = ossaudiodev.open('w') + except IOError, msg: + if msg[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): + raise TestSkipped(msg) + raise test_support.run_unittest(__name__) if __name__ == "__main__": From collinw at gmail.com Wed Apr 25 23:54:35 2007 From: collinw at gmail.com (Collin Winter) Date: Wed, 25 Apr 2007 14:54:35 -0700 Subject: [Python-checkins] buildbot warnings in ia64 Ubuntu trunk trunk In-Reply-To: <20070425213406.4BDDA1E4019@bag.python.org> References: <20070425213406.4BDDA1E4019@bag.python.org> Message-ID: <43aa6ff70704251454p31e8074cr28b4d763dd07168@mail.gmail.com> ====================================================================== > ERROR: test_playback (test.test_ossaudiodev.OSSAudioDevTests) > ---------------------------------------------------------------------- > > Traceback (most recent call last): > File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_ossaudiodev.py", line 149, in test_playback > self.play_sound_file(*sound_info) > File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_ossaudiodev.py", line 50, in play_sound_file > raise TestSkipped(msg) > TestSkipped: [Errno 13] Permission denied: '/dev/dsp' > > ====================================================================== > ERROR: test_set_parameters (test.test_ossaudiodev.OSSAudioDevTests) > ---------------------------------------------------------------------- > > Traceback (most recent call last): > File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_ossaudiodev.py", line 152, in test_set_parameters > dsp = ossaudiodev.open("w") > IOError: [Errno 13] Permission denied: '/dev/dsp' r54974 should fix this. Collin From buildbot at python.org Wed Apr 25 23:59:57 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 21:59:57 +0000 Subject: [Python-checkins] buildbot warnings in S-390 Debian trunk Message-ID: <20070425215957.5C7611E400C@bag.python.org> The Buildbot has detected a new failure of S-390 Debian trunk. Full details are available at: http://www.python.org/dev/buildbot/all/S-390%2520Debian%2520trunk/builds/894 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings test Excerpt from the test logfile: Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/bsddb/test/test_thread.py", line 260, in writerThread self.assertEqual(data, self.makeData(key)) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/unittest.py", line 343, in failUnlessEqual (msg or '%r != %r' % (first, second)) AssertionError: None != '1001-1001-1001-1001-1001' Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/bsddb/test/test_thread.py", line 260, in writerThread self.assertEqual(data, self.makeData(key)) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/unittest.py", line 343, in failUnlessEqual (msg or '%r != %r' % (first, second)) AssertionError: None != '2000-2000-2000-2000-2000' Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/bsddb/test/test_thread.py", line 260, in writerThread self.assertEqual(data, self.makeData(key)) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/unittest.py", line 343, in failUnlessEqual (msg or '%r != %r' % (first, second)) AssertionError: None != '0002-0002-0002-0002-0002' 1 test failed: test_ossaudiodev ====================================================================== ERROR: test_playback (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/test/test_ossaudiodev.py", line 149, in test_playback self.play_sound_file(*sound_info) File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/test/test_ossaudiodev.py", line 50, in play_sound_file raise TestSkipped(msg) TestSkipped: [Errno 2] No such file or directory: '/dev/dsp' ====================================================================== ERROR: test_set_parameters (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-s390/build/Lib/test/test_ossaudiodev.py", line 152, in test_set_parameters dsp = ossaudiodev.open("w") IOError: [Errno 2] No such file or directory: '/dev/dsp' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Thu Apr 26 00:11:37 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 22:11:37 +0000 Subject: [Python-checkins] buildbot warnings in x86 W2k trunk Message-ID: <20070425221137.E8E861E400C@bag.python.org> The Buildbot has detected a new failure of x86 W2k trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520W2k%2520trunk/builds/236 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings failed slave lost sincerely, -The Buildbot From buildbot at python.org Thu Apr 26 00:30:40 2007 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Apr 2007 22:30:40 +0000 Subject: [Python-checkins] buildbot warnings in hppa Ubuntu dapper trunk Message-ID: <20070425223040.A77581E400F@bag.python.org> The Buildbot has detected a new failure of hppa Ubuntu dapper trunk. Full details are available at: http://www.python.org/dev/buildbot/all/hppa%2520Ubuntu%2520dapper%2520trunk/builds/180 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter,tim.peters Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Thu Apr 26 01:33:27 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 26 Apr 2007 01:33:27 +0200 (CEST) Subject: [Python-checkins] r54975 - peps/trunk/pep-3119.txt Message-ID: <20070425233327.501171E400C@bag.python.org> Author: guido.van.rossum Date: Thu Apr 26 01:33:22 2007 New Revision: 54975 Modified: peps/trunk/pep-3119.txt Log: Some small edits, e.g. finite -> sized. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Thu Apr 26 01:33:22 2007 @@ -153,6 +153,11 @@ C() # works +**Note:** The ``@abstractmethod`` decorator should only be used inside +a class body. Dynamically adding abstract methods to a class, or +attempting to modify the abstraction status of a method or class once +it is created, are not supported. + **Implementation:** The ``@abstractmethod`` decorator sets the function attribute ``__isabstractmethod__`` to the value ``True``. The ``type.__new__`` method computes the type attribute @@ -306,13 +311,13 @@ most fundamental set operation is the membership test, written as ``x in s`` and implemented by ``s.__contains__(x)``. This is already taken care of by the `Container`` class defined above. Therefore, we -define a set as finite, iterable container for which certain +define a set as a sized, iterable container for which certain invariants from mathematical set theory hold. The built-in type ``set`` derives from ``MutableSet``. The built-in type ``frozenset`` derives from ``HashableSet``. -You might wonder why we require a set to be finite -- surely certain +You might wonder why we require a set to be sized -- surely certain infinite sets can be represented just fine in Python. For example, the set of even integers could be defined like this:: @@ -326,7 +331,7 @@ out of the scope of a pragmatic proposal like this. ``Set`` - This is a finite, iterable, partially ordered container, i.e. a + This is a sized, iterable, partially ordered container, i.e. a subclass of ``Sized``, ``Iterable``, ``Container`` and ``PartiallyOrdered``. Not every subset of those three classes is a set though! Sets have the additional invariant that each @@ -379,9 +384,9 @@ as dictionary keys. (A similar constraint exists on the hash values for different types of numbers and strings.) - **Open issues:** Should I spell out the hash algorithm? Should - there be another ABC that derives from Set and Hashable (but not - from Composable)? + **Open issues:** Spell out the hash algorithm. Should there be + another ABC that derives from Set and Hashable (but not from + Composable)? ``MutableSet`` This is a subclass of ``ComposableSet`` implementing additional @@ -406,7 +411,9 @@ Abstract method that empties the set. The abstract implementation raises ``NotImplementedError``. (Making this concrete would just add a slow, cumbersome default - implementation.) + implementation.) **Open issues:** Forcing every mutable set + to implement this may be a pain for such a fairly + non-essential method. Perhaps just drop it? ``.pop()`` Concrete method that removes an arbitrary item. If the set is @@ -421,8 +428,10 @@ This also supports the in-place mutating operations ``|=``, ``&=``, ``^=``, ``-=``. These are concrete methods whose right - operand can be an arbitrary ``Iterable``. It does not support the - named methods that perform (almost) the same operations. + operand can be an arbitrary ``Iterable``, except for ``&=``, whose + right operand must be a ``Container``. This ABC does not support + the named methods present on the built-in concrete ``set`` type + that perform (almost) the same operations. Mappings @@ -536,7 +545,9 @@ Python 3000 has two built-in string types: byte strings (``bytes``), deriving from ``MutableSequence``, and (Unicode) character strings -(``str``), deriving from ``HashableSequence``. +(``str``), deriving from ``HashableSequence``. They also derive from +``TotallyOrdered``. If we were to introduce ``Searchable``, they +would also derive from that. **Open issues:** define the base interfaces for these so alternative implementations and subclasses know what they are in for. This may be @@ -544,8 +555,8 @@ ``bytes`` type). -ABCs for Numbers ----------------- +Numbers +------- ABCs for numerical types are defined in PEP 3141. From python-checkins at python.org Thu Apr 26 01:37:42 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 26 Apr 2007 01:37:42 +0200 (CEST) Subject: [Python-checkins] r54976 - sandbox/trunk/abc/abc.py sandbox/trunk/abc/test_abc.py Message-ID: <20070425233742.55AB91E400C@bag.python.org> Author: guido.van.rossum Date: Thu Apr 26 01:37:38 2007 New Revision: 54976 Modified: sandbox/trunk/abc/abc.py sandbox/trunk/abc/test_abc.py Log: Make it match PEP 3119 better. Modified: sandbox/trunk/abc/abc.py ============================================================================== --- sandbox/trunk/abc/abc.py (original) +++ sandbox/trunk/abc/abc.py Thu Apr 26 01:37:38 2007 @@ -1,6 +1,6 @@ #!/usr/bin/env python3.0 -"""Abstract Base Classes experiment. +"""Abstract Base Classes experiment. See PEP 3119. Note: this depends on the brand new Py3k feature that object.__ne__() is implemented by calling __eq__() and reversing the outcome (unless @@ -17,7 +17,12 @@ import sys -### ABC SUPPORT ### +### ABC SUPPORT FRAMEWORK ### + + +# Note: @abstractmethod will become a built-in; Abstract and +# AbstractClass will disappear (the functionality will be subsumed in +# object and type, respectively). def abstractmethod(funcobj): @@ -44,6 +49,9 @@ @abstractmethod def my_abstract_class_method(self, ...): ... + + XXX This example doesn't currently work, since classmethod doesn't + pass through function attributes! I think it should though. """ funcobj.__isabstractmethod__ = True return funcobj @@ -64,64 +72,65 @@ if getattr(value, "__isabstractmethod__", False): abstracts.add(name) cls.__abstractmethods__ = abstracts - if abstracts: - _disable_construction(cls) return cls -def _disable_construction(cls): - """Helper to ensure that a class cannot be instantiated. +class Abstract(metaclass=AbstractClass): + + """Base class to support the abstractmethod decorator. - This is done by planting a __new__ method that raises an exception - if its first argument is the cls argument to this function. + This implicitly sets the metaclass to AbstractClass. """ - # XXX This still may be too much overhead; imagine a concrete class - # deriving from a stack of ABCs, it will bounce off each ABC's - # __new__ method - # XXX Should we store the shadowed function on the class? - # XXX Is it a good idea to name the new function __new__? - dct = cls.__dict__ - shadowed_new = dct.get("__new__") - if not shadowed_new: - @staticmethod - def __new__(c, *a, **k): - if c is cls: - raise AbstractInstantiationError(cls.__abstractmethods__) - return super(cls, c).__new__(c, *a, **k) - else: - @staticmethod - def __new__(c, *a, **k): - if c is cls: - raise AbstractInstantiationError(cls.__abstractmethods__) - return shadowed_new(c, *a, **k) - cls.__new__ = __new__ + def __new__(cls, *args, **kwds): + am = cls.__dict__.get("__abstractmethods__") + if am: + raise TypeError("can't instantiate abstract class %s " + "with abstract methods %s" % + (cls.__name__, ", ".join(sorted(am)))) + return super(Abstract, cls).__new__(cls, *args, **kwds) -class AbstractInstantiationError(TypeError): - """Exception raised when an abstract class is instantiated.""" +### ORDERING ABCS ### - def __init__(self, abstract_methods): - TypeError.__init__(self) - self.abstract_methods = abstract_methods - def __str__(self): - msg = ", ".join(sorted(self.abstract_methods)) - return "Can't instantiate class with abstract method(s) %s" % msg +class PartiallyOrdered(Abstract): - def __repr__(self): - return "AbstractInstantiationError(%r)" % (self.abstract_methods,) + """Partial orderings define a consistent but incomplete < operator. + Invariant: a < b < c => a < c -class Abstract(metaclass=AbstractClass): + It is possible that none of a < b, a == b, a > b hold. + """ - """Base class to support the abstractmethod decorator. + @abstractmethod + def __lt__(self, other): + return NotImplemented - This implicitly sets the metaclass to AbstractClass. + def __le__(self, other): + if not isinstance(other, PartiallyOrdered): + return NotImplemented + # Note that bool(NotImplemented) is True! + return self == other or self.__lt__(other) + + # It's not necessary to define __gt__ and __ge__; these will + # automatically be translated to __lt__ and __le__ calls with + # swapped arguments by the rich comparisons framework. + + +class TotallyOrdered(PartiallyOrdered): + + """Total orderings guarantee that all values are ordered. + + E.g. for any two a and b, exactly one of a < b, a == b, a > b holds. + + XXX What about float? The properties of NaN make it strictly + PartiallyOrdered. But having it TotallyOrdered makes more sense + for most practical purposes. """ -### BASICS ### +### ONE TRICK PONIES ### class Hashable(Abstract): @@ -144,13 +153,13 @@ class Iterator(Iterable): - """An iterator has two methods, __iter__() and next().""" + """An iterator has two methods, __iter__() and __next__().""" @abstractmethod - def next(self): + def __next__(self): raise StopIteration - def __iter__(self): + def __iter__(self): # Concrete! This should always return self return self @@ -158,10 +167,10 @@ """Implementation detail used by Iterable.__iter__().""" - def next(self): - # This will call Iterator.next() and hence will raise StopIteration. - return super(_EmptyIterator, self).next() - # Or: return Iterator.next(self) + def __next__(self): + # This will call Iterator.__next__() which will raise StopIteration. + return super(_EmptyIterator, self).__next__() + # Or: return Iterator.__next__(self) # Or: raise StopIteration @@ -171,6 +180,7 @@ def __len__(self): return 0 + class Container(Abstract): """A container has a __contains__() method.""" @@ -179,22 +189,25 @@ def __contains__(self, elem): return False +class Searchable(Container): -### SETS ### - + """A container whose __contains__ accepts sequences too.""" -class BasicSet(Container, Iterable): + # XXX This is an experiment. Is it worth distinguishing? + # Perhaps later, when we have type annotations so you can write + # Container[T], we can do this: + # + # class Container(Abstract): + # def __contains__(self, val: T) -> bool: ... + # + # class Searchable(Container): + # def __contains__(self, val: T | Sequence[T]) -> bool: ... - """A basic set is an iterable container. - It may not have a length though; it may be infinite! - - XXX Do we care about potentially infinite sets, or sets of - indeterminate size? - """ +### SETS ### -class Set(Container, Iterable, Sized): +class Set(Sized, Iterable, Container, PartiallyOrdered): """A plain set is a finite, iterable container. @@ -227,12 +240,17 @@ return NotImplemented return len(self) == len(other) and self.__le__(other) - # XXX Should we define __ge__ and __gt__ too? - # XXX The following implementations of &, |, ^, - return frozen sets - # because we have to pick a concrete type. They are allowed to - # return any subclass of Set (but Set is not a - # concrete implementation). +class ComposableSet(Set): + + # XXX The following implementations of &, |, ^, - return frozen + # sets because we have to pick a concrete type. They are allowed + # to return any subclass of Set (but Set is not a concrete + # implementation). We return frozen sets because returning set + # may mislead callers from assuming that these operations always + # return mutable sets. + + # XXX Alternatively, we might make these abstract. def __and__(self, other): new = set(self) @@ -255,7 +273,8 @@ return frozenset(new) -class HashableSet(Set, Hashable): +# XXX Should this derive from Set instead of from ComposableSet? +class HashableSet(ComposableSet, Hashable): def __hash__(self): """The hash value must match __eq__. @@ -273,6 +292,68 @@ return h +# XXX Should this derive from Set instead of from ComposableSet? +class MutableSet(ComposableSet): + + @abstractmethod + def add(self, value): + """Return True if it was added, False if already there.""" + raise NotImplementedError + + @abstractmethod + def discard(self, value): + """Return True if it was deleted, False if not there.""" + raise NotImplementedError + + @abstractmethod + def clear(self): + """Implementing this would be bad and slow, hence it's abstract.""" + # XXX It's a pain to have to define this. Maybe leave out? + raise NotImplementedError + + def pop(self): + """Return the popped value. Raise KeyError if empty.""" + it = iter(self) + try: + value = it.__next__() + except StopIteration: + raise KeyError + self.discard(value) + return value + + def toggle(self, value): + """Return True if it was added, False if deleted.""" + # XXX This implementation is not thread-safe + if value in self: + self.discard(value) + return False + else: + self.add(value) + return True + + def __ior__(self, it: Iterable): + for value in it: + self.add(value) + return self + + def __iand__(self, c: Container): + for value in self: + if value not in c: + self.discard(value) + return self + + def __ixor__(self, it: Iterable): + # This calls toggle(), so if that is overridded, we call the override + for value in it: + self.toggle(it) + return self + + def __isub__(self, it: Iterable): + for value in it: + self.discard(value) + return self + + # class set(Set) # class frozenset(HashableSet) @@ -489,7 +570,7 @@ -class Sequence(Sized, Iterable): +class Sequence(Sized, Iterable, Container): """A minimal sequence. @@ -520,6 +601,14 @@ yield self[i] i += 1 + def __contains__(self, value): + for val in self: + if val == value: + return True + return False + + # XXX Do we want all or some of the following? + def __reversed__(self): i = len(self) while i > 0: @@ -527,6 +616,7 @@ yield self[i] def index(self, value): + # XXX Should we add optional start/stop args? Probably not. for i, elem in enumerate(self): if elem == value: return i @@ -547,6 +637,9 @@ repeat = _index(repeat) return self.__class__(elem for i in range(repeat) for elem in self) + # XXX Should we derive from PartiallyOrdered or TotallyOrdered? + # That depends on the items. What if the items aren't orderable? + def __eq__(self, other): if not isinstance(other, Sequence): return NotImplemented Modified: sandbox/trunk/abc/test_abc.py ============================================================================== --- sandbox/trunk/abc/test_abc.py (original) +++ sandbox/trunk/abc/test_abc.py Thu Apr 26 01:37:38 2007 @@ -13,10 +13,10 @@ @abc.abstractmethod def foo(self): pass def bar(self): pass - self.assertRaises(abc.AbstractInstantiationError, C) + self.assertRaises(TypeError, C) class D(C): def bar(self): pass - self.assertRaises(abc.AbstractInstantiationError, D) + self.assertRaises(TypeError, D) class E(D): def foo(self): pass E() From buildbot at python.org Thu Apr 26 02:30:46 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Apr 2007 00:30:46 +0000 Subject: [Python-checkins] buildbot warnings in alpha Debian trunk Message-ID: <20070426003046.830D31E400C@bag.python.org> The Buildbot has detected a new failure of alpha Debian trunk. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Debian%2520trunk/builds/19 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter Build had warnings: warnings test Excerpt from the test logfile: 1 test failed: test_ossaudiodev ====================================================================== ERROR: test_playback (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-alpha/build/Lib/test/test_ossaudiodev.py", line 149, in test_playback self.play_sound_file(*sound_info) File "/home/pybot/buildarea/trunk.klose-debian-alpha/build/Lib/test/test_ossaudiodev.py", line 50, in play_sound_file raise TestSkipped(msg) TestSkipped: [Errno 13] Permission denied: '/dev/dsp' ====================================================================== ERROR: test_set_parameters (test.test_ossaudiodev.OSSAudioDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-alpha/build/Lib/test/test_ossaudiodev.py", line 152, in test_set_parameters dsp = ossaudiodev.open("w") IOError: [Errno 13] Permission denied: '/dev/dsp' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From jimjjewett at gmail.com Thu Apr 26 02:31:39 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Wed, 25 Apr 2007 20:31:39 -0400 Subject: [Python-checkins] ABC PEP -- dropping set.clear Message-ID: On 4/25/07, guido.van.rossum wrote: > + implementation.) **Open issues:** Forcing every mutable set > + to implement this may be a pain for such a fairly > + non-essential method. Perhaps just drop it? There are also comments worrying that an abstract implementation would be horribly slow -- but so what? Alex Martelli posted some stats (for dicts, I think) showing that (even today) clear was slower than just creating a new object. It still makes sense if you care about the "is" relation Since you are keeping "pop", the abstract implementation can at least approximate iteration. def clear(self): while self.pop(): pass -jJ From python-checkins at python.org Thu Apr 26 02:44:41 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 26 Apr 2007 02:44:41 +0200 (CEST) Subject: [Python-checkins] r54977 - peps/trunk/pep-3119.txt Message-ID: <20070426004441.C0B281E400C@bag.python.org> Author: guido.van.rossum Date: Thu Apr 26 02:44:37 2007 New Revision: 54977 Modified: peps/trunk/pep-3119.txt Log: Make clear() a concrete method that calls pop() until it raises KeyError. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Thu Apr 26 02:44:37 2007 @@ -407,14 +407,6 @@ was present and ``False`` if it wasn't. The abstract implementation raises ``NotImplementedError``. - ``.clear()`` - Abstract method that empties the set. The abstract - implementation raises ``NotImplementedError``. (Making this - concrete would just add a slow, cumbersome default - implementation.) **Open issues:** Forcing every mutable set - to implement this may be a pain for such a fairly - non-essential method. Perhaps just drop it? - ``.pop()`` Concrete method that removes an arbitrary item. If the set is empty, it raises ``KeyError``. The default implementation @@ -426,6 +418,14 @@ return ``True`` if ``x`` was added, ``False`` if it was removed. + ``.clear()`` + Concrete method that empties the set. The default + implementation repeatedly calls ``self.pop()`` until + ``KeyError`` is caught. (Note: this is probably much slower + than simply creating a new set, even if an implementation + overrides it with a faster approach; but in some cases object + identity is important.) + This also supports the in-place mutating operations ``|=``, ``&=``, ``^=``, ``-=``. These are concrete methods whose right operand can be an arbitrary ``Iterable``, except for ``&=``, whose @@ -491,8 +491,8 @@ ``MutableMapping`` A subclass of ``Mapping`` that also implements some standard mutating methods. Abstract methods include ``__setitem__``, - ``__delitem__``, ``clear``, ``update``. Concrete methods include - ``pop``, ``popitem``. Note: ``setdefault`` is *not* included. + ``__delitem__``. Concrete methods include ``pop``, ``popitem``, + ``clear``, ``update``. Note: ``setdefault`` is *not* included. **Open issues:** From python-checkins at python.org Thu Apr 26 02:46:21 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 26 Apr 2007 02:46:21 +0200 (CEST) Subject: [Python-checkins] r54978 - sandbox/trunk/abc/abc.py Message-ID: <20070426004621.DAC801E400C@bag.python.org> Author: guido.van.rossum Date: Thu Apr 26 02:46:13 2007 New Revision: 54978 Modified: sandbox/trunk/abc/abc.py Log: Make Set.clear() a concrete method. Modified: sandbox/trunk/abc/abc.py ============================================================================== --- sandbox/trunk/abc/abc.py (original) +++ sandbox/trunk/abc/abc.py Thu Apr 26 02:46:13 2007 @@ -305,12 +305,6 @@ """Return True if it was deleted, False if not there.""" raise NotImplementedError - @abstractmethod - def clear(self): - """Implementing this would be bad and slow, hence it's abstract.""" - # XXX It's a pain to have to define this. Maybe leave out? - raise NotImplementedError - def pop(self): """Return the popped value. Raise KeyError if empty.""" it = iter(self) @@ -331,6 +325,14 @@ self.add(value) return True + def clear(self): + """This is slow (creates N new iterators!) but effective.""" + try: + while True: + self.pop() + except KeyError: + pass + def __ior__(self, it: Iterable): for value in it: self.add(value) @@ -517,6 +519,10 @@ return False +# XXX HashableMapping +# XXX MutableMapping + + ### SEQUENCES ### From buildbot at python.org Thu Apr 26 04:06:24 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Apr 2007 02:06:24 +0000 Subject: [Python-checkins] buildbot warnings in MIPS Debian trunk Message-ID: <20070426020624.0327A1E4018@bag.python.org> The Buildbot has detected a new failure of MIPS Debian trunk. Full details are available at: http://www.python.org/dev/buildbot/all/MIPS%2520Debian%2520trunk/builds/772 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: collin.winter,tim.peters Build had warnings: warnings failed slave lost sincerely, -The Buildbot From python-checkins at python.org Thu Apr 26 06:42:21 2007 From: python-checkins at python.org (fred.drake) Date: Thu, 26 Apr 2007 06:42:21 +0200 (CEST) Subject: [Python-checkins] r54979 - python/trunk/Doc/lib/libbase64.tex python/trunk/Doc/lib/liblogging.tex python/trunk/Doc/lib/libstdtypes.tex python/trunk/Doc/lib/libxmlrpclib.tex Message-ID: <20070426044221.336EA1E4020@bag.python.org> Author: fred.drake Date: Thu Apr 26 06:42:19 2007 New Revision: 54979 Modified: python/trunk/Doc/lib/libbase64.tex python/trunk/Doc/lib/liblogging.tex python/trunk/Doc/lib/libstdtypes.tex python/trunk/Doc/lib/libxmlrpclib.tex Log: fix some markup errors Modified: python/trunk/Doc/lib/libbase64.tex ============================================================================== --- python/trunk/Doc/lib/libbase64.tex (original) +++ python/trunk/Doc/lib/libbase64.tex Thu Apr 26 06:42:19 2007 @@ -85,7 +85,7 @@ letter O (oh), and for optional mapping of the digit 1 (one) to either the letter I (eye) or letter L (el). The optional argument \var{map01} when not \code{None}, specifies which letter the digit 1 should -be mapped to (when map01 is not \var{None}, the digit 0 is always +be mapped to (when \var{map01} is not \code{None}, the digit 0 is always mapped to the letter O). For security purposes the default is \code{None}, so that 0 and 1 are not allowed in the input. Modified: python/trunk/Doc/lib/liblogging.tex ============================================================================== --- python/trunk/Doc/lib/liblogging.tex (original) +++ python/trunk/Doc/lib/liblogging.tex Thu Apr 26 06:42:19 2007 @@ -1528,7 +1528,7 @@ \var{exc_info} is the exception tuple obtained by calling \function{sys.exc_info() }(or \constant{None}, if no exception information is available). The \var{func} is the name of the function from which the -logging call was made. If not specified, it defaults to \var{None}. +logging call was made. If not specified, it defaults to \code{None}. \versionchanged[\var{func} was added]{2.5} \end{classdesc} Modified: python/trunk/Doc/lib/libstdtypes.tex ============================================================================== --- python/trunk/Doc/lib/libstdtypes.tex (original) +++ python/trunk/Doc/lib/libstdtypes.tex Thu Apr 26 06:42:19 2007 @@ -1496,7 +1496,7 @@ \item[(5)] \function{setdefault()} is like \function{get()}, except that if \var{k} is missing, \var{x} is both returned and inserted into -the dictionary as the value of \var{k}. \var{x} defaults to \var{None}. +the dictionary as the value of \var{k}. \var{x} defaults to \code{None}. \item[(6)] \function{popitem()} is useful to destructively iterate over a dictionary, as often used in set algorithms. If the dictionary @@ -1855,7 +1855,7 @@ expection that occurred should be suppressed. If an exception occurred while executing the body of the \keyword{with} statement, the arguments contain the exception type, value and traceback information. - Otherwise, all three arguments are \var{None}. + Otherwise, all three arguments are \code{None}. Returning a true value from this method will cause the \keyword{with} statement to suppress the exception and continue execution with the Modified: python/trunk/Doc/lib/libxmlrpclib.tex ============================================================================== --- python/trunk/Doc/lib/libxmlrpclib.tex (original) +++ python/trunk/Doc/lib/libxmlrpclib.tex Thu Apr 26 06:42:19 2007 @@ -287,7 +287,7 @@ Create an object used to boxcar method calls. \var{server} is the eventual target of the call. Calls can be made to the result object, -but they will immediately return \var{None}, and only store the +but they will immediately return \code{None}, and only store the call name and parameters in the \class{MultiCall} object. Calling the object itself causes all stored calls to be transmitted as a single \code{system.multicall} request. The result of this call From python-checkins at python.org Thu Apr 26 06:43:58 2007 From: python-checkins at python.org (fred.drake) Date: Thu, 26 Apr 2007 06:43:58 +0200 (CEST) Subject: [Python-checkins] r54981 - python/branches/release25-maint/Doc/lib/libbase64.tex python/branches/release25-maint/Doc/lib/liblogging.tex python/branches/release25-maint/Doc/lib/libstdtypes.tex python/branches/release25-maint/Doc/lib/libxmlrpclib.tex Message-ID: <20070426044358.E39301E400D@bag.python.org> Author: fred.drake Date: Thu Apr 26 06:43:58 2007 New Revision: 54981 Modified: python/branches/release25-maint/Doc/lib/libbase64.tex python/branches/release25-maint/Doc/lib/liblogging.tex python/branches/release25-maint/Doc/lib/libstdtypes.tex python/branches/release25-maint/Doc/lib/libxmlrpclib.tex Log: fix some markup errors Modified: python/branches/release25-maint/Doc/lib/libbase64.tex ============================================================================== --- python/branches/release25-maint/Doc/lib/libbase64.tex (original) +++ python/branches/release25-maint/Doc/lib/libbase64.tex Thu Apr 26 06:43:58 2007 @@ -85,7 +85,7 @@ letter O (oh), and for optional mapping of the digit 1 (one) to either the letter I (eye) or letter L (el). The optional argument \var{map01} when not \code{None}, specifies which letter the digit 1 should -be mapped to (when map01 is not \var{None}, the digit 0 is always +be mapped to (when \var{map01} is not \code{None}, the digit 0 is always mapped to the letter O). For security purposes the default is \code{None}, so that 0 and 1 are not allowed in the input. Modified: python/branches/release25-maint/Doc/lib/liblogging.tex ============================================================================== --- python/branches/release25-maint/Doc/lib/liblogging.tex (original) +++ python/branches/release25-maint/Doc/lib/liblogging.tex Thu Apr 26 06:43:58 2007 @@ -1495,7 +1495,7 @@ \var{exc_info} is the exception tuple obtained by calling \function{sys.exc_info() }(or \constant{None}, if no exception information is available). The \var{func} is the name of the function from which the -logging call was made. If not specified, it defaults to \var{None}. +logging call was made. If not specified, it defaults to \code{None}. \versionchanged[\var{func} was added]{2.5} \end{classdesc} Modified: python/branches/release25-maint/Doc/lib/libstdtypes.tex ============================================================================== --- python/branches/release25-maint/Doc/lib/libstdtypes.tex (original) +++ python/branches/release25-maint/Doc/lib/libstdtypes.tex Thu Apr 26 06:43:58 2007 @@ -1489,7 +1489,7 @@ \item[(5)] \function{setdefault()} is like \function{get()}, except that if \var{k} is missing, \var{x} is both returned and inserted into -the dictionary as the value of \var{k}. \var{x} defaults to \var{None}. +the dictionary as the value of \var{k}. \var{x} defaults to \code{None}. \item[(6)] \function{popitem()} is useful to destructively iterate over a dictionary, as often used in set algorithms. If the dictionary @@ -1846,7 +1846,7 @@ expection that occurred should be suppressed. If an exception occurred while executing the body of the \keyword{with} statement, the arguments contain the exception type, value and traceback information. - Otherwise, all three arguments are \var{None}. + Otherwise, all three arguments are \code{None}. Returning a true value from this method will cause the \keyword{with} statement to suppress the exception and continue execution with the Modified: python/branches/release25-maint/Doc/lib/libxmlrpclib.tex ============================================================================== --- python/branches/release25-maint/Doc/lib/libxmlrpclib.tex (original) +++ python/branches/release25-maint/Doc/lib/libxmlrpclib.tex Thu Apr 26 06:43:58 2007 @@ -280,7 +280,7 @@ Create an object used to boxcar method calls. \var{server} is the eventual target of the call. Calls can be made to the result object, -but they will immediately return \var{None}, and only store the +but they will immediately return \code{None}, and only store the call name and parameters in the \class{MultiCall} object. Calling the object itself causes all stored calls to be transmitted as a single \code{system.multicall} request. The result of this call From python-checkins at python.org Thu Apr 26 11:15:11 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Thu, 26 Apr 2007 11:15:11 +0200 (CEST) Subject: [Python-checkins] r54982 - in python/trunk: Include/fileobject.h Modules/posixmodule.c Objects/fileobject.c Message-ID: <20070426091511.5F99B1E4010@bag.python.org> Author: kristjan.jonsson Date: Thu Apr 26 11:15:08 2007 New Revision: 54982 Modified: python/trunk/Include/fileobject.h python/trunk/Modules/posixmodule.c python/trunk/Objects/fileobject.c Log: Export function sanitize_the_mode from fileobject.c as _PyFile_SanitizeMode(). Use this function in posixmodule.c when implementing fdopen(). This fixes test_subprocess.py for a VisualStudio 2005 compile. Modified: python/trunk/Include/fileobject.h ============================================================================== --- python/trunk/Include/fileobject.h (original) +++ python/trunk/Include/fileobject.h Thu Apr 26 11:15:08 2007 @@ -57,6 +57,11 @@ char *Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *); size_t Py_UniversalNewlineFread(char *, size_t, FILE *, PyObject *); +/* A routine to do sanity checking on the file mode string. returns + non-zero on if an exception occurred +*/ +int _PyFile_SanitizeMode(char *mode); + #ifdef __cplusplus } #endif Modified: python/trunk/Modules/posixmodule.c ============================================================================== --- python/trunk/Modules/posixmodule.c (original) +++ python/trunk/Modules/posixmodule.c Thu Apr 26 11:15:08 2007 @@ -6259,16 +6259,23 @@ posix_fdopen(PyObject *self, PyObject *args) { int fd; - char *mode = "r"; + char *orgmode = "r"; int bufsize = -1; FILE *fp; PyObject *f; - if (!PyArg_ParseTuple(args, "i|si", &fd, &mode, &bufsize)) + char *mode; + if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize)) return NULL; - if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') { - PyErr_Format(PyExc_ValueError, - "invalid file mode '%s'", mode); + /* Sanitize mode. See fileobject.c */ + mode = PyMem_MALLOC(strlen(orgmode)+3); + if (!mode) { + PyErr_NoMemory(); + return NULL; + } + strcpy(mode, orgmode); + if (_PyFile_SanitizeMode(mode)) { + PyMem_FREE(mode); return NULL; } Py_BEGIN_ALLOW_THREADS @@ -6289,10 +6296,11 @@ #else fp = fdopen(fd, mode); #endif + PyMem_FREE(mode); Py_END_ALLOW_THREADS if (fp == NULL) return posix_error(); - f = PyFile_FromFile(fp, "", mode, fclose); + f = PyFile_FromFile(fp, "", orgmode, fclose); if (f != NULL) PyFile_SetBufSize(f, bufsize); return f; Modified: python/trunk/Objects/fileobject.c ============================================================================== --- python/trunk/Objects/fileobject.c (original) +++ python/trunk/Objects/fileobject.c Thu Apr 26 11:15:08 2007 @@ -139,17 +139,16 @@ ignore stuff they don't understand... write or append mode with universal newline support is expressly forbidden by PEP 278. Additionally, remove the 'U' from the mode string as platforms - won't know what it is. */ -/* zero return is kewl - one is un-kewl */ -static int -sanitize_the_mode(char *mode) + won't know what it is. Non-zero return signals an exception */ +int +_PyFile_SanitizeMode(char *mode) { char *upos; size_t len = strlen(mode); if (!len) { PyErr_SetString(PyExc_ValueError, "empty mode string"); - return 1; + return -1; } upos = strchr(mode, 'U'); @@ -160,7 +159,7 @@ PyErr_Format(PyExc_ValueError, "universal newline " "mode can only be used with modes " "starting with 'r'"); - return 1; + return -1; } if (mode[0] != 'r') { @@ -175,7 +174,7 @@ } else if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') { PyErr_Format(PyExc_ValueError, "mode string must begin with " "one of 'r', 'w', 'a' or 'U', not '%.200s'", mode); - return 1; + return -1; } return 0; @@ -204,7 +203,7 @@ } strcpy(newmode, mode); - if (sanitize_the_mode(newmode)) { + if (_PyFile_SanitizeMode(newmode)) { f = NULL; goto cleanup; } From buildbot at python.org Thu Apr 26 11:24:18 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Apr 2007 09:24:18 +0000 Subject: [Python-checkins] buildbot warnings in amd64 gentoo trunk Message-ID: <20070426092418.F11811E400D@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%2520gentoo%2520trunk/builds/1983 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: fred.drake,kristjan.jonsson Build had warnings: warnings test Excerpt from the test logfile: make: *** [buildbottest] Segmentation fault (core dumped) sincerely, -The Buildbot From nnorwitz at gmail.com Thu Apr 26 11:31:39 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 26 Apr 2007 05:31:39 -0400 Subject: [Python-checkins] Python Regression Test Failures all (1) Message-ID: <20070426093139.GA6157@python.psfb.org> test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_StringIO test___all__ test___future__ test__locale test_aepack test_aepack skipped -- No module named aepack test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat WARNING: failed to listen on port 54322, trying another test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bufio test_bz2 test_cProfile test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd_line test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_crypt test_csv test_ctypes test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils test_dl test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_float test_fnmatch test_fork1 test_format test_fpformat test_frozen test_ftplib test test_ftplib failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_ftplib.py", line 59, in testTimeoutConnect ftp.connect("localhost", timeout=30) File "/tmp/python-test/local/lib/python2.6/ftplib.py", line 129, in connect self.sock = socket.create_connection((self.host, self.port), self.timeout) File "/tmp/python-test/local/lib/python2.6/socket.py", line 443, in create_connection raise error, msg error: (111, 'Connection refused') test_funcattrs test_functools test_future test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hexoct test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_index test_inspect test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_largefile test_list test_locale test_logging test_long test_long_future test_longexp test_macfs test_macfs skipped -- No module named macfs test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_mutants test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os test_parser test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- test works only on NT+ test_pep292 test_pep352 test_pickle test_pickletools test_pkg test_pkgimport test_platform test_plistlib test_plistlib skipped -- No module named plistlib test_poll test_popen [7328 refs] [7328 refs] [7328 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_profile test_profilehooks test_pty test_pwd test_pyclbr test_pyexpat test_queue test_quopri [7703 refs] [7703 refs] test_random test_re test_repr test_resource test_rfc822 test_rgbimg test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site test_slice test_smtplib test_socket test_socket_ssl test_socketserver test_softspace test_sort test_sqlite test_startfile test_startfile skipped -- cannot import name startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_struct test_structmembers test_structseq test_subprocess [7323 refs] [7321 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7321 refs] [8869 refs] [7539 refs] [7324 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] [7323 refs] . [7323 refs] [7323 refs] this bit of output is from a test of stdout in a different process ... [7323 refs] [7323 refs] [7539 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [7323 refs] [7323 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test test_telnetlib failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.6/test/test_telnetlib.py", line 41, in testTimeoutDefault telnet = telnetlib.Telnet("localhost", 9091) File "/tmp/python-test/local/lib/python2.6/telnetlib.py", line 209, in __init__ self.open(host, port, timeout) File "/tmp/python-test/local/lib/python2.6/telnetlib.py", line 227, in open self.sock = socket.create_connection((host, port), self.timeout) File "/tmp/python-test/local/lib/python2.6/socket.py", line 443, in create_connection raise error, msg error: (111, 'Connection refused') test_tempfile [7327 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading test_threading_local test_threadsignals test_time test_timeout test_tokenize test_trace test_traceback test_transformer test_tuple test_ucn test_unary test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2net test_urllibnet test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid WARNING: uuid.getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._ifconfig_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. WARNING: uuid._unixdll_getnode is unreliable on many platforms. It is disabled until the code and/or test can be fixed properly. test_wait3 test_wait4 test_warnings test_wave test_weakref test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zlib 301 tests OK. 2 tests failed: test_ftplib test_telnetlib 21 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_cd test_cl test_gl test_imgfile test_ioctl test_macfs test_macostools test_pep277 test_plistlib test_scriptpackages test_startfile test_sunaudiodev test_tcl test_unicode_file test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_ioctl warning: DBTxn aborted in destructor. No prior commit() or abort(). [491015 refs] From python-checkins at python.org Thu Apr 26 15:44:20 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Thu, 26 Apr 2007 15:44:20 +0200 (CEST) Subject: [Python-checkins] r54983 - python/trunk/Lib/test/test_locale.py Message-ID: <20070426134420.6FA441E400B@bag.python.org> Author: kristjan.jonsson Date: Thu Apr 26 15:44:16 2007 New Revision: 54983 Modified: python/trunk/Lib/test/test_locale.py Log: The locale "En" appears not to be valid on windows underi VisualStudio.2005. Added "English" to the test_locale.py to make the testsuite pass for that build Modified: python/trunk/Lib/test/test_locale.py ============================================================================== --- python/trunk/Lib/test/test_locale.py (original) +++ python/trunk/Lib/test/test_locale.py Thu Apr 26 15:44:16 2007 @@ -7,7 +7,7 @@ oldlocale = locale.setlocale(locale.LC_NUMERIC) if sys.platform.startswith("win"): - tlocs = ("en",) + tlocs = ("En", "English") else: tlocs = ("en_US.UTF-8", "en_US.US-ASCII", "en_US") From python-checkins at python.org Thu Apr 26 16:23:17 2007 From: python-checkins at python.org (steve.holden) Date: Thu, 26 Apr 2007 16:23:17 +0200 (CEST) Subject: [Python-checkins] r54984 - python/trunk/Doc/tut/tut.tex Message-ID: <20070426142317.992E61E400B@bag.python.org> Author: steve.holden Date: Thu Apr 26 16:23:12 2007 New Revision: 54984 Modified: python/trunk/Doc/tut/tut.tex Log: Minor wording change on slicing aide-memoire. Modified: python/trunk/Doc/tut/tut.tex ============================================================================== --- python/trunk/Doc/tut/tut.tex (original) +++ python/trunk/Doc/tut/tut.tex Thu Apr 26 16:23:12 2007 @@ -813,7 +813,7 @@ IndexError: string index out of range \end{verbatim} -The best way to remember how slices work is to think of the indices as +One way to remember how slices work is to think of the indices as pointing \emph{between} characters, with the left edge of the first character numbered 0. Then the right edge of the last character of a string of \var{n} characters has index \var{n}, for example: From facundobatista at gmail.com Thu Apr 26 16:34:38 2007 From: facundobatista at gmail.com (Facundo Batista) Date: Thu, 26 Apr 2007 11:34:38 -0300 Subject: [Python-checkins] Python Regression Test Failures all (1) In-Reply-To: <20070426093139.GA6157@python.psfb.org> References: <20070426093139.GA6157@python.psfb.org> Message-ID: 2007/4/26, Neal Norwitz : > ... > test_ftplib > test test_ftplib failed -- Traceback (most recent call last): > File "/tmp/python-test/local/lib/python2.6/test/test_ftplib.py", line 59, in testTimeoutConnect > ftp.connect("localhost", timeout=30) > File "/tmp/python-test/local/lib/python2.6/ftplib.py", line 129, in connect > self.sock = socket.create_connection((self.host, self.port), self.timeout) > File "/tmp/python-test/local/lib/python2.6/socket.py", line 443, in create_connection > raise error, msg > error: (111, 'Connection refused') > > ... > > test_telnetlib > test test_telnetlib failed -- Traceback (most recent call last): > File "/tmp/python-test/local/lib/python2.6/test/test_telnetlib.py", line 41, in testTimeoutDefault > telnet = telnetlib.Telnet("localhost", 9091) > File "/tmp/python-test/local/lib/python2.6/telnetlib.py", line 209, in __init__ > self.open(host, port, timeout) > File "/tmp/python-test/local/lib/python2.6/telnetlib.py", line 227, in open > self.sock = socket.create_connection((host, port), self.timeout) > File "/tmp/python-test/local/lib/python2.6/socket.py", line 443, in create_connection > raise error, msg > error: (111, 'Connection refused') Very, very strange. I rerun the tests in my machine, like: facundo at expiron: .../trunk$ ./python -O Lib/test/regrtest.py -u network And the result is: 294 tests OK. 4 tests failed: test_descr test_timeout test_urllib2net test_urllibnet 29 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_curses test_gl test_imgfile test_linuxaudiodev test_macfs test_macostools test_normalization test_ossaudiodev test_pep277 test_plistlib test_scriptpackages test_startfile test_sunaudiodev test_tcl test_winreg test_winsound test_zipfile64 1 skip unexpected on linux2: test_tcl Without the "-u network", only fails test_descr. Which errors we had here?: test test_timeout failed -- Traceback (most recent call last): File "/home/facundo/devel/reps/python/trunk/Lib/test/test_timeout.py", line 128, in testConnectTimeout %(_delta, self.fuzz, _timeout)) AssertionError: timeout (5.25138) is more than 2 seconds more than expected (0.001) test test_urllib2net failed -- Traceback (most recent call last): File "/home/facundo/devel/reps/python/trunk/Lib/test/test_urllib2net.py", line 147, in test_bad_address urllib2.urlopen, "http://www.python.invalid./") AssertionError: IOError not raised test_urllibnet test test_urllibnet failed -- Traceback (most recent call last): File "/home/facundo/devel/reps/python/trunk/Lib/test/test_urllibnet.py", line 113, in test_bad_address urllib.urlopen, "http://www.python.invalid./") AssertionError: IOError not raised The last two are not errors at all, just OpenDNS returning me name searches, and not an error. The timeout is strange, never happened to me before... And see that here ftplib and telnetlib worked ok... Anybody else is seen this kind of spurious errors? Regards, -- . Facundo Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org/ar/ From python-checkins at python.org Thu Apr 26 17:25:01 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Thu, 26 Apr 2007 17:25:01 +0200 (CEST) Subject: [Python-checkins] r54985 - python/trunk/Modules/_bsddb.c Message-ID: <20070426152501.ABF681E400C@bag.python.org> Author: kristjan.jonsson Date: Thu Apr 26 17:24:54 2007 New Revision: 54985 Modified: python/trunk/Modules/_bsddb.c Log: Accomodate 64 bit time_t in the _bsddb module. Modified: python/trunk/Modules/_bsddb.c ============================================================================== --- python/trunk/Modules/_bsddb.c (original) +++ python/trunk/Modules/_bsddb.c Thu Apr 26 17:24:54 2007 @@ -749,6 +749,24 @@ Py_XDECREF(v); } + +/* The same, when the value is a time_t */ +static void _addTimeTToDict(PyObject* dict, char *name, time_t value) +{ + PyObject* v; + /* if the value fits in regular int, use that. */ +#ifdef HAVE_LONG_LONG + if (sizeof(time_t) > sizeof(long)) + v = PyLong_FromLongLong((PY_LONG_LONG) value); + else +#endif + v = PyInt_FromLong((long) value); + if (!v || PyDict_SetItemString(dict, name, v)) + PyErr_Clear(); + + Py_XDECREF(v); +} + #if (DBVER >= 43) /* add an db_seq_t to a dictionary using the given name as a key */ static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value) @@ -4633,8 +4651,9 @@ } #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) +#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name) - MAKE_ENTRY(time_ckp); + MAKE_TIME_T_ENTRY(time_ckp); MAKE_ENTRY(last_txnid); MAKE_ENTRY(maxtxns); MAKE_ENTRY(nactive); @@ -4647,6 +4666,7 @@ MAKE_ENTRY(region_nowait); #undef MAKE_ENTRY +#undef MAKE_TIME_T_ENTRY free(sp); return d; } From buildbot at python.org Thu Apr 26 20:21:18 2007 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Apr 2007 18:21:18 +0000 Subject: [Python-checkins] buildbot warnings in hppa Ubuntu dapper trunk Message-ID: <20070426182118.F26D91E400B@bag.python.org> The Buildbot has detected a new failure of hppa Ubuntu dapper trunk. Full details are available at: http://www.python.org/dev/buildbot/all/hppa%2520Ubuntu%2520dapper%2520trunk/builds/184 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: kristjan.jonsson,steve.holden Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Thu Apr 26 20:24:12 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 26 Apr 2007 20:24:12 +0200 (CEST) Subject: [Python-checkins] r54986 - peps/trunk/pep-3119.txt Message-ID: <20070426182412.0A4131E400B@bag.python.org> Author: guido.van.rossum Date: Thu Apr 26 20:24:07 2007 New Revision: 54986 Modified: peps/trunk/pep-3119.txt Log: Deal with some open issues. Add some others. Will be posting soon. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Thu Apr 26 20:24:07 2007 @@ -7,7 +7,7 @@ Type: Standards Track Content-Type: text/x-rst Created: 18-Apr-2007 -Post-History: Not yet posted +Post-History: 26-Apr-2007 Abstract @@ -213,19 +213,18 @@ ``PartiallyOrdered`` This ABC defines the 4 inequality operations ``<``, ``<=``, ``>=``, ``>``. (Note that ``==`` and ``!=`` are defined by ``object``.) - Classes deriving from this ABC should satisfy weak invariants such - as ``a < b < c`` implies ``a < c`` but don't require that for any - two instances ``x`` and ``y`` exactly one of ``x < y``, ``x == y`` - or ``x >= y`` apply. + Classes deriving from this ABC should implement a partial order + as defined in mathematics. [9]_ ``TotallyOrdered`` This ABC derives from ``PartiallyOrdered``. It adds no new - operations but implies a promise of stronger invariants. **Open - issues:** Should ``float`` derive from ``TotallyOrdered`` even - though for ``NaN`` this isn't strictly correct? + operations but implies a promise of stronger invariants. + Classes deriving from this ABC should implement a total order + as defined in mathematics. [10]_ **Open issues:** Where should these live? The ``collections`` module -doesn't seem right. +doesn't seem right, but making them built-ins seems a slippery slope +too. One Trick Ponies @@ -252,7 +251,7 @@ instances only, ``__hash__`` for those instances should raise a ``TypeError`` exception. - Note: being an instance of this class does not imply that an + **Note:** being an instance of this class does not imply that an object is immutable; e.g. a tuple containing a list as a member is not immutable; its ``__hash__`` method raises ``TypeError``. @@ -266,7 +265,7 @@ The base class for classes defining ``__next__``. This derives from ``Iterable``. The abstract ``__next__`` method raises ``StopIteration``. The concrete ``__iter__`` method returns - ``self``. (Note: this assumes PEP 3114 is implemented.) + ``self``. ``Sized`` The base class for classes defining ``__len__``. The ``__len__`` @@ -274,13 +273,7 @@ The abstract ``__len__`` method returns 0. **Invariant:** If a class ``C`` derives from ``Sized`` as well as from ``Iterable``, the invariant ``sum(1 for x in o) == len(o)`` should hold for any - instance ``o`` of ``C``. **Open issues:** Is ``Sized`` the best - name? Proposed alternatives already tentatively rejected: - ``Finite`` (nobody understood it), ``Lengthy``, ``Sizeable`` (both - too cute), ``Countable`` (the set of natural numbers is a - countable set in math), ``Enumerable`` (sounds like a sysnonym for - ``Iterable``), ``Dimension``, ``Extent`` (sound like numbers to - me), ``Bounded`` (probably just as confusing as ``Fininte``). + instance ``o`` of ``C``. ``Container`` The base class for classes defining ``__contains__``. The @@ -290,7 +283,7 @@ ``Iterable``, then ``(x in o for x in o)`` should be a generator yielding only True values for any instance ``o`` of ``C``. - Note: strictly speaking, there are three variants of this method's + **Note:** strictly speaking, there are three variants of this method's semantics. The first one is for sets and mappings, which is fast: O(1) or O(log N). The second one is for membership checking on sequences, which is slow: O(N). The third one is for subsequence @@ -337,25 +330,31 @@ a set though! Sets have the additional invariant that each element occurs only once (as can be determined by iteration), and in addition sets define concrete operators that implement the - inequality operations as subclass/superclass tests. + inequality operations as subclass/superclass tests. In general, + the invariants for finite sets in mathematics hold. [11]_ Sets with different implementations can be compared safely, - efficiently and correctly. Because ``Set`` derives from - ``Sized``, ``__eq__`` takes a shortcut and returns ``False`` - immediately if two sets of unequal length are compared. - Similarly, ``__le__`` returns ``False`` immediately if the first - set has more members than the second set. Note that set inclusion - implements only a partial ordering; e.g. ``{1, 2}`` and ``{1, 3}`` - are not ordered (all three of ``<``, ``==`` and ``>`` return - ``False`` for these arguments). Sets cannot be ordered relative - to mappings or sequences, but they can be compared for equality - (and then they always compare unequal). + (usually) efficiently and correctly using the mathematical + definitions of the subclass/superclass operations for finite sets. + The ordering operations have concrete implementations; subclasses + may override these for speed but should maintain the semantics. + Because ``Set`` derives from ``Sized``, ``__eq__`` may take a + shortcut and returns ``False`` immediately if two sets of unequal + length are compared. Similarly, ``__le__`` may return ``False`` + immediately if the first set has more members than the second set. + Note that set inclusion implements only a partial ordering; + e.g. ``{1, 2}`` and ``{1, 3}`` are not ordered (all three of + ``<``, ``==`` and ``>`` return ``False`` for these arguments). + Sets cannot be ordered relative to mappings or sequences, but they + can be compared to those for equality (and then they always + compare unequal). - Note: the ``issubset`` and ``issuperset`` methods found on the set - type in Python 2 are not supported, as these are mostly just + **Note:** the ``issubset`` and ``issuperset`` methods found on the + set type in Python 2 are not supported, as these are mostly just aliases for ``__le__`` and ``__ge__``. - **Open issues:** Spell out the invariants and method definitions. + **Open issues:** should we define comparison of instances of + different concrete set types this way? ``ComposableSet`` This is a subclass of ``Set`` that defines abstract operators to @@ -366,14 +365,22 @@ ``NotImplementedError``; this is because any generic implementation would have to create new instances but the ABCs don't (and shouldn't, IMO) provide an API for creating new - instances. **Invariants:** The implementations of these operators - should ensure that the results match the mathematical definition - of set composition. - - **Open issues:** Should I spell out the invariants? Should we - define an API for creating new instances (e.g. a class method or a - fixed constructor signature)? Should we just pick a concrete - return type (e.g. ``set``)? + instances. The implementations of these operators should ensure + that the results match the mathematical definition of set + composition. [11]_ + + **Open issues:** Should ``__or__`` and friends be abstract or + concrete methods? Making them abstract means that every + ComposableSet implementation must reimplement all of them. But + making them concrete begs the question of the actual return type: + since the ABC doesn't (and IMO shouldn't) define the constructor + signature for subclasses, the concrete implementations in the ABC + don't have an API to construct a new instance given an iterable. + Perhaps the right choice is to have a static concrete factory + function ``fromiterable`` which takes an iterable and returns + a ``ComposableSet`` instance. Subclasses can override this and + benefit from the default implementations of ``__or__`` etc.; or + they can override ``__or__`` if they want to. ``HashableSet`` This is a subclass of both ``ComposableSet`` and ``Hashable``. It @@ -385,8 +392,8 @@ values for different types of numbers and strings.) **Open issues:** Spell out the hash algorithm. Should there be - another ABC that derives from Set and Hashable (but not from - Composable)? + another ABC that derives from Set and Hashable, but not from + Composable? ``MutableSet`` This is a subclass of ``ComposableSet`` implementing additional @@ -421,7 +428,7 @@ ``.clear()`` Concrete method that empties the set. The default implementation repeatedly calls ``self.pop()`` until - ``KeyError`` is caught. (Note: this is probably much slower + ``KeyError`` is caught. (**Note:** this is likely much slower than simply creating a new set, even if an implementation overrides it with a faster approach; but in some cases object identity is important.) @@ -467,21 +474,52 @@ raise ``KeyError``, and ``False`` if it does. ``Mapping`` - A subclass of ``BasicMapping``, ``iterable`` and ``Sized``. It - defines concrete methods ``__eq__``, ``keys``, ``items``, - ``values``. Iterating over a mapping should return all the valid - keys (i.e. those keys for which ``.__getitem__()`` returns a - value), once each, and nothing else. The lengh of a mapping - should equal to the number of elements returned by iterating over - the object until the end of the iterator is reached (this is - implied by the invariant listed above for ``Sized``). Two - mappings, even with different implementations, can be compared for - equality, and are considered equal if and only iff their items - compare equal when converted to sets. The ``keys``, ``items`` and - ``values`` methods return views; ``keys`` and ``items`` return - ``Set`` views, ``values`` returns a ``Container`` view. The - following invariant should hold: m.items() == set(zip(m.keys(), - m.values())). + A subclass of ``BasicMapping``, ``Iterable`` and ``Sized``. The + keys of a mapping naturally form a set. The (key, value) pairs + are also referred to as items. The items also form a set. + Methods: + + ``__len__`` + Abstract method returning the length of the key set. + + ``__iter__`` + Abstract method returning each key in the key set exactly once. + + ``__eq__`` + Concrete method for comparing mappings. Two mappings, even + with different implementations, can be compared for equality, + and are considered equal if and only iff their item sets are + equal. **Open issues:** should we define comparison of + instances of different concrete mapping types this way? + + ``keys`` + Concrete method returning the key set as a ``Set``. The + default concrete implementation returns a "view" on the key + set (meaning if the underlying mapping is modified, the view's + value changes correspondingly); subclasses are not required to + return a view but they should return a ``Set``. + + ``items`` + Concrete method returning the items as a ``Set``. The default + concrete implementation returns a "view" on the item set; + subclasses are not required to return a view but they should + return a ``Set``. + + ``values`` + Concrete method returning the values as a sized, iterable + container (not a set!). The default concrete implementation + returns a "view" on the values of the mapping; subclasses are + not required to return a view but they should return a sized, + iterable container. + + The following invariant should hold for any mapping ``m``:: + + set(m.items()) == set(zip(m.keys(), m.values())) + + i.e. iterating over the keys and the values in parallel should + return *corresponding* keys and values. **Open issues:** Should + this always be required? How about the stronger invariant using + ``list()`` instead of ``set()``? ``HashableMapping`` A subclass of ``Mapping`` and ``Hashable``. The values should be @@ -492,11 +530,8 @@ A subclass of ``Mapping`` that also implements some standard mutating methods. Abstract methods include ``__setitem__``, ``__delitem__``. Concrete methods include ``pop``, ``popitem``, - ``clear``, ``update``. Note: ``setdefault`` is *not* included. - -**Open issues:** - -* We should say more about mapping view types. + ``clear``, ``update``. **Note:** ``setdefault`` is *not* included. + **Open issues:** Write out the specs for the methods. Sequences @@ -510,7 +545,7 @@ ``Sequence`` A subclass of ``Iterable``, ``Sized``, ``Container``. It - defines a new abstract method ``__getitem__`` that has a + defines a new abstract method ``__getitem__`` that has a somewhat complicated signature: when called with an integer, it returns an element of the sequence or raises ``IndexError``; when called with a ``slice`` object, it returns another ``Sequence``. The concrete @@ -535,10 +570,19 @@ well as slices), ``__delitem__`` (ditto), ``insert``, ``append``, ``reverse``. Concrete mutating methods: ``extend``, ``pop``, ``remove``. Concrete mutating operators: ``+=``, ``*=`` (these - mutate the object in place). Note: this does not define + mutate the object in place). **Note:** this does not define ``sort()`` -- that is only required to exist on genuine ``list`` instances. +**Open issues:** If all the elements of a sequence are totally +ordered, the sequence itself can be totally ordered with respect to +other sequences containing corresponding items of the same type. +Should we reflect this by making ``Sequence`` derive from +``TotallyOrdered``? Or ``Partiallyordered``? Also, we could easily +define comparison of sequences of different types, so that e.g. +``(1, 2, 3) == [1, 2, 3]`` and ``(1, 2) < [1, 2, 3]``. Should we? +(It might imply ``["a", "b"] == "ab"`` and ``[1, 2] == b"\1\2"``.) + Strings ------- @@ -686,10 +730,19 @@ .. [7] Unifying types and classes in Python 2.2, by GvR (http://www.python.org/download/releases/2.2.3/descrintro/) -.. [8] "Putting Metaclasses to Work: A New Dimension in Object-Oriented - Programming", by Ira R. Forman and Scott H. Danforth +.. [8] Putting Metaclasses to Work: A New Dimension in Object-Oriented + Programming, by Ira R. Forman and Scott H. Danforth (http://www.amazon.com/gp/product/0201433052) +.. [9] Partial order, in Wikipedia + (http://en.wikipedia.org/wiki/Partial_order) + +.. [10] Total order, in Wikipedia + (http://en.wikipedia.org/wiki/Total_order) + +.. [11] Finite set, in Wikipedia + (http://en.wikipedia.org/wiki/Finite_set) + Copyright ========= From python-checkins at python.org Thu Apr 26 20:26:12 2007 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 26 Apr 2007 20:26:12 +0200 (CEST) Subject: [Python-checkins] r54987 - sandbox/trunk/abc/abc.py Message-ID: <20070426182612.373F01E400B@bag.python.org> Author: guido.van.rossum Date: Thu Apr 26 20:26:08 2007 New Revision: 54987 Modified: sandbox/trunk/abc/abc.py Log: Make it match the current PEP 3119 a little more (e.g. SizedMapping->Mapping). Experiment with implementing set composition operations a little differently. Modified: sandbox/trunk/abc/abc.py ============================================================================== --- sandbox/trunk/abc/abc.py (original) +++ sandbox/trunk/abc/abc.py Thu Apr 26 20:26:08 2007 @@ -15,6 +15,7 @@ __author__ = "Guido van Rossum " import sys +import itertools ### ABC SUPPORT FRAMEWORK ### @@ -252,25 +253,33 @@ # XXX Alternatively, we might make these abstract. + @staticmethod + def fromiterable(it): + return frozenset(it) + def __and__(self, other): - new = set(self) - new.intersection_update(other) - return frozenset(new) + if not isinstance(other, Iterable): + return NotImplemented + return self.fromiterable(value for value in other if value in self) def __or__(self, other): - new = set(self) - new.update(other) - return frozenset(new) + return self.fromiterable(itertools.chain(self, other)) def __xor__(self, other): - new = set(self) - new.symmetric_difference_update(other) - return frozenset(new) + if not isinstance(other, Set): + if not isinstance(other, Iterable): + return NotImplemented + other = self.fromiterable(other) + return self.fromiterable(itertool.chain( + (value for value in self if value not in other), + (other for value in other if value not in self))) def __sub__(self, other): - new = set(self) - new.difference_update(other) - return frozenset(new) + if not isinstance(other, Set): + if not isinstance(other, Iterable): + return NotImplemented + other = self.fromiterable(other) + return self.fromiterable(value for value in self if value not in other) # XXX Should this derive from Set instead of from ComposableSet? @@ -448,19 +457,19 @@ yield self._mapping[key] -class SizedMapping(IterableMapping, Sized): +class Mapping(IterableMapping, Sized): def keys(self): - return SizedKeysView(self) + return KeysView(self) def items(self): - return SizedItemsView(self) + return ItemsView(self) def values(self): - return SizedValuesView(self) + return ValuesView(self) def __eq__(self, other): - if not isinstance(other, SizedMapping): + if not isinstance(other, Mapping): return NotImplemented if len(other) != len(self): return False @@ -476,21 +485,21 @@ return True -class _SizedMappingView(_MappingView, Sized): +class _MappingView(_MappingView, Sized): def __len__(self): return len(self._mapping) -class SizedKeysView(_SizedMappingView, KeysView, Set): +class KeysView(_MappingView, KeysView, Set): pass -class SizedItemsView(_SizedMappingView, ItemsView, Set): +class ItemsView(_MappingView, ItemsView, Set): pass -class SizedValuesView(_SizedMappingView, ValuesView): +class ValuesView(_MappingView, ValuesView): def __eq__(self, other): if not (isinstance(other, Sized) and isinstance(other, Iterable)): @@ -723,10 +732,10 @@ return len(self.adaptee) -class AdaptToMapping(SizedMapping): +class AdaptToMapping(Mapping): def __new__(cls, adaptee): - self = SizedMapping.__new__(cls) + self = Mapping.__new__(cls) self.adaptee = adaptee return self From jimjjewett at gmail.com Thu Apr 26 21:30:48 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Thu, 26 Apr 2007 15:30:48 -0400 Subject: [Python-checkins] r54986 - peps/trunk/pep-3119.txt In-Reply-To: <20070426182412.0A4131E400B@bag.python.org> References: <20070426182412.0A4131E400B@bag.python.org> Message-ID: On 4/26/07, guido.van.rossum wrote: > New Revision: 54986 > peps/trunk/pep-3119.txt > + **Open issues:** Should ``__or__`` and friends be abstract or > + concrete methods? ... ... > + Perhaps the right choice is to have a static concrete factory > + function ``fromiterable`` which takes an iterable and returns > + a ``ComposableSet`` instance. I like it; it seems to clutter the interface a bit, but for sets, it probably is a reasonable requirement that there be such a constructor. And in the worst case, they get a builtin set instead of their own type, but only for methods they didn't bother to implement. > + The following invariant should hold for any mapping ``m``:: > + > + set(m.items()) == set(zip(m.keys(), m.values())) > + > + i.e. iterating over the keys and the values in parallel should > + return *corresponding* keys and values. **Open issues:** Should > + this always be required? How about the stronger invariant using > + ``list()`` instead of ``set()``? You might as well; I can certainly imagine an implementation that does not march in parallel for keys and value; it is hard to imagine a (non-silly) example that keeps those two in parallel, but somehow forgets the order when grabbing them together. > +**Open issues:** If all the elements of a sequence are totally > +ordered, the sequence itself can be totally ordered with respect to > +other sequences containing corresponding items of the same type. > +Should we reflect this by making ``Sequence`` derive from > +``TotallyOrdered``? Or ``Partiallyordered``? I don't think it is TotallyOrdered, because some sequence instances will have unordered elements. Saying it is PartiallyOrdered might start down the road of placing too many constraints on the ordering of ABC bases. (Unless you use the non-inheritance way to assert this...) > Also, we could easily > +define comparison of sequences of different types, so that e.g. > +``(1, 2, 3) == [1, 2, 3]`` and ``(1, 2) < [1, 2, 3]``. Should we? > +(It might imply ``["a", "b"] == "ab"`` and ``[1, 2] == b"\1\2"``.) I think that might be too much of a backwards-compatibility problem. If (("1", "2", "3") == "123"), that will shrink some dictionaries. -jJ From python-checkins at python.org Thu Apr 26 23:43:31 2007 From: python-checkins at python.org (travis.oliphant) Date: Thu, 26 Apr 2007 23:43:31 +0200 (CEST) Subject: [Python-checkins] r54988 - peps/trunk/pep-3118.txt Message-ID: <20070426214331.7CAC61E400B@bag.python.org> Author: travis.oliphant Date: Thu Apr 26 23:43:28 2007 New Revision: 54988 Modified: peps/trunk/pep-3118.txt Log: Changes to pep-3118.txt Modified: peps/trunk/pep-3118.txt ============================================================================== --- peps/trunk/pep-3118.txt (original) +++ peps/trunk/pep-3118.txt Thu Apr 26 23:43:28 2007 @@ -1,8 +1,9 @@ + PEP: 3118 Title: Revising the buffer protocol Version: $Revision$ Last-Modified: $Date$ -Author: Travis Oliphant , Carl Banks +Authors: Travis Oliphant , Carl Banks Status: Draft Type: Standards Track Content-Type: text/x-rst @@ -13,8 +14,8 @@ ======== This PEP proposes re-designing the buffer interface (PyBufferProcs -function pointers) to improve the way Python allows memory sharing -in Python 3.0 +function pointers) to improve the way Python allows memory sharing in +Python 3.0 In particular, it is proposed that the character buffer portion of the API be elminated and the multiple-segment portion be @@ -73,7 +74,7 @@ NumPy uses the notion of constant striding in each dimension as its basic concept of an array. With this concept, a simple sub-region - of a larger array can be described without copying the data. T + of a larger array can be described without copying the data. Thus, stride information is the additional information that must be shared. @@ -151,7 +152,7 @@ :: - typedef int (*getbufferproc)(PyObject *obj, struct bufferinfo *view, int flags) + typedef int (*getbufferproc)(PyObject *obj, PyBuffer *view, int flags) This function returns 0 on success and -1 on failure (and raises an error). The first variable is the "exporting" object. The second @@ -160,54 +161,137 @@ obtained. In this case, the corresponding releasebuffer should also be called with NULL. -The third argument indicates what kind of buffer the exporter is allowed to return. It tells the -exporter what elements the bufferinfo structure the consumer is going to make use of. This -allows the exporter to simplify and/or raise an error if it can't support the operation. - -It also allows the caller to make a request for a simple "view" and -receive it or have an error raised if it's not possible. - -All of the following assume that at least buf, len, and readonly will be -utilized by the caller. - - Py_BUF_SIMPLE - The returned buffer will only be assumed to be readable (the object - may or may not have writeable memory). Only the buf, len, and - readonly variables may be accessed. The format will be - assumed to be unsigned bytes. This is a "stand-alone" flag constant. - It never needs to be \|'d to the others. - - Py_BUF_WRITEABLE - The returned buffer must be writeable. If it cannot be, then raise an error. - - Py_BUF_READONLY - The returned buffer must be readonly and the underlying object should make - its memory readonly if that is possible. - - Py_BUF_FORMAT - The consumer will be using the format string information so make sure that - member is filled correctly. - - Py_BUF_SHAPE - The consumer can (and might) make use of using the ndims and shape members of the structure - so make sure they are filled in correctly. +The third argument indicates what kind of buffer the consumer is +prepared to deal with and therefore what kind of buffer the exporter +is allowed to return. The new buffer interface allows for much more +complicated memory sharing possibilities. Some consumers may not be +able to handle all the complexibity but may want to see if the +exporter will let them take a simpler view to its memory. + +In addition, some exporters may not be able to share memory in every +possible way and may need to raise errors to signal to some consumers +that something is just not possible. These errors should be +PyErr_BufferError unless there is another error that is actually +causing the problem. The exporter can use flags information to +simplify how much of the PyBuffer structure is filled in with +non-default values and/or raise an error if the object can't support a +simpler view of its memory. + +The exporter should always fill in all elements of the buffer +structure (with defaults if nothing else is requested). + +Some flags are useful for requesting a specific kind of memory +segment, while others indicate to the exporter what kind of +information the consumer can deal with. If certain information is not +asked for by the consumer, but the exporter cannot share its memory +without that information, then a PyErr_BufferError should be raised. + + +PyBUF_SIMPLE + + This is the default flag state (0). The returned buffer may or may + not have writeable memory. The format will be assumed to be + unsigned bytes . This is a "stand-alone" flag constant. It never + needs to be |'d to the others. The exporter will raise an error if + it cannot provide such a contiguous buffer of bytes. + +PyBUF_REQ_WRITEABLE + + The returned buffer must be writeable. If it is not writeable, + then raise an error. + +PyBUF_REQ_LOCKDATA + + The returned buffer must be readonly. If the object is already + read-only or it can make its memory read-only (and there are no + other views on the object) then it should do so and return the + buffer information. If the object does not have read-only memory + (or cannot make it read-only), then an error should be raised. + +PyBUF_REQ_FORMAT + + The returned buffer must have true format information if this flag + is provided. This would be used when the consumer is going to be + checking for what 'kind' of data is actually stored. An exporter + should always be able to provide this information if requested. If + format is not explicitly requested then the format must be returned + as NULL (which means "B") + +PyBUF_REQ_ALIGNED (implies PyBUF_REQ_FORMAT) + + The returned buffer must have all (primitive data-type entries) + aligned as the compiler would align them + +PyBUF_ALW_ND + + The returned buffer must provide shape information. The memory will + be assumed C-style contiguous (last dimension varies the fastest). + The exporter may raise an error if it cannot provide this kind of + contiguous buffer. - Py_BUF_STRIDES (implies SHAPE) - The consumer can (and might) make use of the strides member of the structure (as well - as ndims and shape) - - Py_BUF_OFFSETS (implies STRIDES) - The consumer can (and might) make use of the suboffsets member (as well as - ndims, shape, and strides) - -Thus, the consumer simply wanting an contiguous chunk of bytes from -the object would use Py_BUF_SIMPLE, while a consumer that understands -how to make use of the most complicated cases would use -Py_BUF_OFFSETS. +PyBUF_ALW_STRIDES (implies PyBUF_ALW_ND) + + The returned buffer must provide strides information. This would be + used when the consumer can handle strided, discontiguous arrays. + Handling strides automatically assumes you can handle shape. + The exporter may raise an error if cannot provide a strided-only + representation of the data (i.e. without the suboffsets). + +PyBUF_REQ_C_CONTIGUOUS +PyBUF_REQ_F_CONTIGUOUS +PyBUF_REQ_ANY_CONTIGUOUS + + These flags indicate that the returned buffer must be respectively, + C-contiguous (last dimension varies the fastest), Fortran + contiguous (first dimension varies the fastest) or either one. + All of these flags imply PyBUF_ALW_STRIDES and guarantee that the + strides buffer info structure will be filled in correctly. + + +PyBUF_ALW_INDIRECT (implies PyBUF_ALW_STRIDES) + + The returned buffer must have suboffsets information. This would + be used when the consumer can handle indirect array referencing + implied by these suboffsets. + + +Specialized combinations of flags for specific kinds of memory_sharing. + + Multi-dimensional (but contiguous) + + PyBUF_CONTIG (PyBUF_ALW_ND | PyBUF_REQ_WRITEABLE | PyBUF_REQ_ALIGNED) + PyBUF_CONTIG_RO (PyBUF_ALW_ND | PyBUF_REQ_ALIGNED) + PyBUF_CONTIG_LCK (PyBUF_ALW_ND | PyBUF_REQ_LOCKDATA | PyBUF_REQ_ALIGNED) + + Multi-dimensional using strides but aligned + + PyBUF_STRIDED (PyBUF_ALW_STRIDES | PyBUF_REQ_WRITEABLE | PyBUF_REQ_ALIGNED) + PyBUF_STRIDED_RO (PyBUF_ALW_STRIDES | PyBUF_REQ_ALIGNED) + PyBUF_STRIDED_LCK (PyBUF_ALW_STRIDES | PyBUF_REQ_LOCKDATA | PyBUF_REQ_ALIGNED) + + Multi-dimensional using strides and not necessarily aligned + + PyBUF_RECORDS (PyBUF_ALW_STRIDES | PyBUF_REQ_WRITEABLE | PyBUF_REQ_FORMAT) + PyBUF_RECORDS_RO (PyBUF_ALW_STRIDES | PyBUF_REQ_FORMAT) + PyBUF_RECORDS_LCK (PyBUF_ALW_STRIDES | PyBUF_REQ_LOCKDATA | PyBUF_REQ_FORMAT) + + Multi-dimensional using sub-offsets + + PyBUF_FULL (PyBUF_ALW_INDIRECT | PyBUF_REQ_WRITEABLE | PyBUF_REQ_FORMAT) + PyBUF_FULL_RO (PyBUF_ALW_INDIRECT | PyBUF_REQ_FORMAT) + PyBUF_FULL_LCK (PyBUF_ALW_INDIRECT | PyBUF_REQ_LOCKDATA | PyBUF_REQ_FORMAT) + +Thus, the consumer simply wanting a contiguous chunk of bytes from +the object would use PyBUF_SIMPLE, while a consumer that understands +how to make use of the most complicated cases could use PyBUF_FULL + +The format information is only guaranteed to be non-NULL if +PyBUF_REQ_FORMAT is in the flag argument, otherwise it is expected the +consumer will assume unsigned bytes. There is a C-API that simple exporting objects can use to fill-in the buffer info structure correctly according to the provided flags if a -contiguous chunk of memory is all that can be exported. +contiguous chunk of "unsigned bytes" is all that can be exported. The bufferinfo structure is:: @@ -216,21 +300,23 @@ void *buf; Py_ssize_t len; int readonly; - char *format; - int ndims; + const char *format; + int ndim; Py_ssize_t *shape; Py_ssize_t *strides; Py_ssize_t *suboffsets; + int itemsize; void *internal; - }; + } PyBuffer; -Before calling this function, the bufferinfo structure can be filled with -whatever. Upon return from getbufferproc, the bufferinfo structure is filled in -with relevant information about the buffer. This same bufferinfo -structure must be passed to bf_releasebuffer (if available) when the -consumer is done with the memory. The caller is responsible for -keeping a reference to obj until releasebuffer is called (i.e. this -call does not alter the reference count of obj). +Before calling this function, the bufferinfo structure can be filled +with whatever. Upon return from getbufferproc, the bufferinfo +structure is filled in with relevant information about the buffer. +This same bufferinfo structure must be passed to bf_releasebuffer (if +available) when the consumer is done with the memory. The caller is +responsible for keeping a reference to obj until releasebuffer is +called (i.e. the call to bf_getbuffer does not alter the reference +count of obj). The members of the bufferinfo structure are: @@ -242,33 +328,39 @@ same as the product of the shape array multiplied by the number of bytes per item of memory. -readonly - an integer variable to hold whether or not the memory is - readonly. 1 means the memory is readonly, zero means the - memory is writeable. +readonly + an integer variable to hold whether or not the memory is readonly. + 1 means the memory is readonly, zero means the memory is + writeable, and -1 means the memory was "locked" (changed from + writeable to readonly) when this PyBuffer structure was filled-in + and therefore should be unlocked when this PyBuffer structure is + "released" (this is supported only by some exporters). format a NULL-terminated format-string (following the struct-style syntax including extensions) indicating what is in each element of memory. The number of elements is len / itemsize, where itemsize - is the number of bytes implied by the format. For standard - unsigned bytes use a format string of "B". + is the number of bytes implied by the format. This can be NULL which + implies standard unsigned bytes ("B"). ndims a variable storing the number of dimensions the memory represents. - Must be >=0. + Must be >=0. A value of 0 means that shape and strides and suboffsets + must be NULL (i.e. the memory represents a scalar). shape an array of ``Py_ssize_t`` of length ``ndims`` indicating the shape of the memory as an N-D array. Note that ``((*shape)[0] * - ... * (*shape)[ndims-1])*itemsize = len``. + ... * (*shape)[ndims-1])*itemsize = len``. If ndims is 0 (indicating + a scalar), then this must be NULL. strides address of a ``Py_ssize_t*`` variable that will be filled with a - pointer to an array of ``Py_ssize_t`` of length ``*ndims`` - indicating the number of bytes to skip to get to the next element - in each dimension. For C-style contiguous arrays (where the - last-dimension varies the fastest) this must be filled in. + pointer to an array of ``Py_ssize_t`` of length ``ndims`` (or NULL + if ndims is 0). indicating the number of bytes to skip to get to + the next element in each dimension. If this is not requested by + the caller (PyBUF_ALW_STRIDES is not set), then this should be set + to NULL which indicates a C-style contiguous array. suboffsets address of a ``Py_ssize_t *`` variable that will be filled with a @@ -279,14 +371,14 @@ suboffset value that it negative indicates that no de-referencing should occur (striding in a contiguous memory block). If all suboffsets are negative (i.e. no de-referencing is needed, then - this must be NULL. + this must be NULL (the default value). For clarity, here is a function that returns a pointer to the element in an N-D array pointed to by an N-dimesional index when - there are both strides and suboffsets.:: + there are both non-NULL strides and suboffsets.:: void* get_item_pointer(int ndim, void* buf, Py_ssize_t* strides, - Py_ssize_t* suboffsets, Py_ssize_t *indices) { + Py_ssize_t* suboffsets, Py_ssize_t *indices) { char* pointer = (char*)buf; int i; for (i = 0; i < ndim; i++) { @@ -304,28 +396,36 @@ the location of the starting pointer directly (i.e. buf would be modified). +itemsize + This is a storage for the itemsize of each element of the shared + memory. It is strictly un-necessary as it can be obtained using + PyBuffer_SizeFromFormat, however an exporter may know this + information without parsing the format string and it is necessary + to know the itemsize for proper interpretation of striding. + Therefore, storing it is more convenient and faster. + internal This is for use internally by the exporting object. For example, this might be re-cast as an integer by the exporter and used to store flags about whether or not the shape, strides, and suboffsets arrays must be freed when the buffer is released. The consumer - should never touch this value. + should never alter this value. -The exporter is responsible for making sure the memory pointed to by -buf, format, shape, strides, and suboffsets is valid until +The exporter is responsible for making sure that any memory pointed to +by buf, format, shape, strides, and suboffsets is valid until releasebuffer is called. If the exporter wants to be able to change -shape, strides, and/or suboffsets before releasebuffer is called then -it should allocate those arrays when getbuffer is called (pointing to -them in the buffer-info structure provided) and free them when -releasebuffer is called. +an object's shape, strides, and/or suboffsets before releasebuffer is +called then it should allocate those arrays when getbuffer is called +(pointing to them in the buffer-info structure provided) and free them +when releasebuffer is called. The same bufferinfo struct should be used in the release-buffer interface call. The caller is responsible for the memory of the bufferinfo structure itself. -``typedef int (*releasebufferproc)(PyObject *obj, struct bufferinfo *view)`` +``typedef int (*releasebufferproc)(PyObject *obj, PyBuffer *view)`` Callers of getbufferproc must make sure that this function is called when memory previously acquired from the object is no longer needed. The exporter of the interface must make sure that @@ -348,7 +448,8 @@ All that is specifically required by the exporter, however, is to ensure that any memory shared through the bufferinfo structure remains -valid until releasebuffer is called on the bufferinfo structure. +valid until releasebuffer is called on the bufferinfo structure +exporting that memory. New C-API calls are proposed @@ -362,69 +463,94 @@ :: - int PyObject_GetBuffer(PyObject *obj, struct bufferinfo *view, int flags) + int PyObject_GetBuffer(PyObject *obj, PyBuffer *view, + int flags) This is a C-API version of the getbuffer function call. It checks to make sure object has the required function pointer and issues the -call. Returns -1 and raises an error on failure and returns 0 on -success. +call. Returns -1 and raises an error on failure and returns 0 on +success. :: + int PyObject_ReleaseBuffer(PyObject *obj, PyBuffer *view) - int PyObject_ReleaseBuffer(PyObject *obj, struct bufferinfo *view) - -This is a C-API version of the releasebuffer function call. It checks to -make sure the object has the required function pointer and issues the call. Returns 0 -on success and -1 (with an error raised) on failure. This function always -succeeds if there is no releasebuffer function for the object. +This is a C-API version of the releasebuffer function call. It checks +to make sure the object has the required function pointer and issues +the call. Returns 0 on success and -1 (with an error raised) on +failure. This function always succeeds if there is no releasebuffer +function for the object. :: PyObject *PyObject_GetMemoryView(PyObject *obj) -Return a memory-view object from an object that defines the buffer interface. -If make_ro is non-zero then request that the memory is made read-only until -release buffer is called. +Return a memory-view object from an object that defines the buffer interface. + +A memory-view object is an extended buffer object that could replace +the buffer object (but doesn't have to as that could be kept as a +simple 1-d memory-view object). It's C-structure is -A memory-view object is an extended buffer object that should replace -the buffer object in Python 3K. It's C-structure is:: +:: typedef struct { PyObject_HEAD PyObject *base; - struct bufferinfo view; - int itemsize; - int flags; + int ndims; + Py_ssize_t *starts; /* slice starts */ + Py_ssize_t *stops; /* slice stops */ + Py_ssize_t *steps; /* slice steps */ } PyMemoryViewObject; -This is very similar to the current buffer object except offset has -been removed because ptr can just be modified by offset and a single -offset is not sufficient for the sub-offsets. Also the hash has been -removed because using the buffer object as a hash even if it is -read-only is rarely useful. - -Also, the format, ndims, shape, strides, and suboffsets have been -added. These additions will allow multi-dimensional slicing of the -memory-view object which can be added at some point. This object -always owns it's own shape, strides, and suboffsets arrays and it's -own format string, but always borrows the memory from the object -pointed to by base. - -The itemsize is a convenience and specifies the number of bytes -indicated by the format string if positive. - -This object never reallocates ptr, shape, strides, subboffsets or -format and therefore does not need to keep track of how many views it -has exported. - -It exports a view using the base object. It releases a view by -releasing the view on the base object. Because, it will never -re-allocate memory, it does not need to keep track of how many it has -exported but simple reference counting will suffice. +This is functionally similar to the current buffer object except only +a reference to base is kept. The actual memory for base must be +re-grabbed using the buffer-protocol, whenever it is actually +needed (after which it is immediately released). + +The getbuffer and releasebuffer for this object use the underlying +base object (adjusted as needed using the slice information). If the +number of dimensions of the base object (or the strides or the size) +has changed when a new view is requested, then the getbuffer will +trigger an error. Methods on the MemoryView object will allow +manual locking and unlocking of the underlying buffer. + +This memory-view object will support mult-dimensional slicing and be +the first object provided with Python to do so. Slices of the +memory-view object are other memory-view objects. When an "element" +from the memory-view is returned it is always a bytes object whose +format should be interpreted by the format attribute of the memoryview +object. The struct module can be used to "decode" the bytes in Python +if desired. + +The Python name will be + +__builtin__.memory + +Methods: + + lock + unlock + __getitem__ (will support multi-dimensional slicing) + __setitem__ (will support multi-dimensional slicing) + tobytes (obtain a bytes-object of everything in the memory). + tolist (obtain a "nested" list of the memory. Everything + is interpreted into standard Python objects + as the struct module unpack would do). + +Attributes (taken from the memory of the base object) + + format + itemsize + shape + strides + suboffsets + size + readonly + ndim + :: - int PyObject_SizeFromFormat(char *) + int PyBuffer_SizeFromFormat(const char *) Return the implied itemsize of the data-format area from a struct-style description. @@ -432,65 +558,82 @@ :: int PyObject_GetContiguous(PyObject *obj, void **buf, Py_ssize_t *len, - int fortran) + char **format, char fortran) Return a contiguous chunk of memory representing the buffer. If a copy is made then return 1. If no copy was needed return 0. If an error occurred in probing the buffer interface, then return -1. The contiguous chunk of memory is pointed to by ``*buf`` and the length of that memory is ``*len``. If the object is multi-dimensional, then if -fortran is 1, the first dimension of the underlying array will vary -the fastest in the buffer. If fortran is 0, then the last dimension -will vary the fastest (C-style contiguous). If fortran is -1, then it +fortran is 'F', the first dimension of the underlying array will vary +the fastest in the buffer. If fortran is 'C', then the last dimension +will vary the fastest (C-style contiguous). If fortran is 'A', then it does not matter and you will get whatever the object decides is more -efficient. +efficient. If a copy is made, then the memory must be freed by calling +``PyMem_Free``. :: int PyObject_CopyToObject(PyObject *obj, void *buf, Py_ssize_t len, - int fortran) + char fortran) Copy ``len`` bytes of data pointed to by the contiguous chunk of memory pointed to by ``buf`` into the buffer exported by obj. Return 0 on success and return -1 and raise an error on failure. If the object does not have a writeable buffer, then an error is raised. If -fortran is 1, then if the object is multi-dimensional, then the data +fortran is 'F', then if the object is multi-dimensional, then the data will be copied into the array in Fortran-style (first dimension varies -the fastest). If fortran is 0, then the data will be copied into the -array in C-style (last dimension varies the fastest). If fortran is -1, then +the fastest). If fortran is 'C', then the data will be copied into the +array in C-style (last dimension varies the fastest). If fortran is 'A', then it does not matter and the copy will be made in whatever way is more efficient. -The last two C-API calls allow a standard way of getting data in and + +These last three C-API calls allow a standard way of getting data in and out of Python objects into contiguous memory areas no matter how it is actually stored. These calls use the extended buffer interface to perform their work. :: - int PyObject_IsContiguous(struct bufferinfo *view, int fortran); + int PyBuffer_IsContiguous(PyBuffer *view, char fortran); -Return 1 if the memory defined by the view object is C-style (fortran = 0) -or Fortran-style (fortran = 1) contiguous. Return 0 otherwise. +Return 1 if the memory defined by the view object is C-style (fortran += 'C') or Fortran-style (fortran = 'F') contiguous or either one +(fortran = 'A'). Return 0 otherwise. :: + int PyBuffer_IsAligned(PyBuffer *view); - void PyObject_FillContiguousStrides(int *ndims, Py_ssize_t *shape, +Return 1 if the memory at all elements of the array implied by the +view object is aligned + +:: + + void PyBuffer_FillContiguousStrides(int *ndims, Py_ssize_t *shape, int itemsize, - Py_ssize_t *strides, int fortran) + Py_ssize_t *strides, char fortran) Fill the strides array with byte-strides of a contiguous (C-style if fortran is 0 or Fortran-style if fortran is 1) array of the given shape with the given number of bytes per element. :: + int PyBuffer_FillInfo(PyBuffer *view, void *buf, + Py_ssize_t len, int readonly, int infoflags) + +Fills in a buffer-info structure correctly for an exporter that can +only share a contiguous chunk of memory of "unsigned bytes" of the +given length. Returns 0 on success and -1 (with raising an error) on +error. - int PyObject_FillBufferInfo(struct bufferinfo *view, void *buf, Py_ssize_t len, - int readonly, int infoflags) +:: + PyErr_BufferError -Fills in a buffer-info structure correctly for an exporter that can only share -a contiguous chunk of memory of "unsigned bytes" of the given length. Returns 0 on success -and -1 (with raising an error) on error +A new error object for returning buffer errors which arise because an +exporter cannot provide the kind of buffer that a consumer expects. +This will also be raised when a consumer requests a buffer from an +object that does not provide the protocol. Additions to the struct string-syntax @@ -521,22 +664,29 @@ ':name:' optional name of the preceeding element 'X{}' pointer to a function (optional function signature inside {}) -' \n\t' ignored (allow better readability) -- this may already be true +' \n\t' ignored (allow better readability) + -- this may already be true ================ =========== The struct module will be changed to understand these as well and -return appropriate Python objects on unpacking. Un-packing a +return appropriate Python objects on unpacking. Unpacking a long-double will return a decimal object or a ctypes long-double. Unpacking 'u' or 'w' will return Python unicode. Unpacking a -multi-dimensional array will return a list of lists. Un-packing a -pointer will return a ctypes pointer object. Un-packing a bit will -return a Python Bool. Spaces in the struct-string syntax will be -ignored. Unpacking a named-object will return a Python class with -attributes having those names. - -Endian-specification ('=','>','<') is also allowed inside the -string so that it can change if needed. The previously-specified -endian string is in force until changed. The default endian is '='. +multi-dimensional array will return a list (of lists if >1d). +Unpacking a pointer will return a ctypes pointer object. Unpacking a +function pointer will return a ctypes call-object (perhaps). Unpacking +a bit will return a Python Bool. White-space in the struct-string +syntax will be ignored if it isn't already. Unpacking a named-object +will return some kind of named-tuple-like object that acts like a +tuple but whose entries can also be accessed by name. Unpacking a +nested structure will return a nested tuple. + +Endian-specification ('!', '@','=','>','<', '^') is also allowed +inside the string so that it can change if needed. The +previously-specified endian string is in force until changed. The +default endian is '@' which means native data-types and alignment. If +un-aligned, native data-types are requested, then the endian +specification is '^'. According to the struct-module, a number can preceed a character code to specify how many of that type there are. The @@ -551,16 +701,21 @@ ==================================== Here are some examples of C-structures and how they would be -represented using the struct-style syntax: +represented using the struct-style syntax. + + is the constructor for a named-tuple (not-specified yet). float - 'f' + 'f' <--> Python float complex double - 'Zd' + 'Zd' <--> Python complex RGB Pixel data - 'BBB' or 'B:r: B:g: B:b:' + 'BBB' <--> (int, int, int) + 'B:r: B:g: B:b:' <--> ((int, int, int), ('r','g','b')) + Mixed endian (weird but possible) - '>i:big: i:big: ((int, int), ('big', 'little')) + Nested structure :: @@ -586,7 +741,9 @@ int ival; double data[16*4]; } - 'i:ival: (16,4)d:data:' + """i:ival: + (16,4)d:data: + """ Code to be affected @@ -662,10 +819,12 @@ ========= Ex. 1 ----------- +----------- This example shows how an image object that uses contiguous lines might expose its buffer.:: +:: + struct rgba { unsigned char r, g, b, a; }; @@ -688,7 +847,9 @@ So what does ImageObject's getbuffer do? Leaving error checking out:: - int Image_getbuffer(PyObject *self, struct bufferinfo *view, int flags) { +:: + + int Image_getbuffer(PyObject *self, PyBuffer *view, int flags) { static Py_ssize_t suboffsets[2] = { -1, 0 }; @@ -710,7 +871,7 @@ } - int Image_releasebuffer(PyObject *self, struct bufferinfo *view) { + int Image_releasebuffer(PyObject *self, PyBuffer *view) { self->view_count--; return 0; } @@ -721,33 +882,36 @@ This example shows how an object that wants to expose a contiguous chunk of memory (which will never be re-allocated while the object is -alive) would do that.:: +alive) would do that. - int myobject_getbuffer(PyObject *self, struct bufferinfo *view, int flags) { +:: - void *buf; - Py_ssize_t len; - int readonly=0; - - buf = /* Point to buffer */ - len = /* Set to size of buffer */ - readonly = /* Set to 1 if readonly */ + int myobject_getbuffer(PyObject *self, PyBuffer *view, int flags) { - return PyObject_FillBufferInfo(view, buf, len, readonly, flags); + void *buf; + Py_ssize_t len; + int readonly=0; + + buf = /* Point to buffer */ + len = /* Set to size of buffer */ + readonly = /* Set to 1 if readonly */ + + return PyObject_FillBufferInfo(view, buf, len, readonly, flags); } - /* No releasebuffer is necessary because the memory will never - be re-allocated so the locking mechanism is not needed - */ +/* No releasebuffer is necessary because the memory will never +be re-allocated so the locking mechanism is not needed +*/ Ex. 3 ----------- A consumer that wants to only get a simple contiguous chunk of bytes -from a Python object, obj would do the following:: +from a Python object, obj would do the following: +:: - struct bufferinfo view; + PyBuffer view; int ret; if (PyObject_GetBuffer(obj, &view, Py_BUF_SIMPLE) < 0) { @@ -767,7 +931,36 @@ } +Ex. 4 +----------- + +A consumer that wants to be able to use any object's memory but is +writing an algorithm that only handle contiguous memory could do the following: + +:: + + void *buf; + Py_ssize_t len; + char *format; + + if (PyObject_GetContiguous(obj, &buf, &len, &format, 0) < 0) { + /* error return */ + } + + /* process memory pointed to by buffer if format is correct */ + /* Optional: + + if, after processing, we want to copy data from buffer back + into the the object + + we could do + */ + + if (PyObject_CopyToObject(obj, buf, len, 0) < 0) { + /* error return */ + } + Copyright ========= From python-checkins at python.org Fri Apr 27 00:33:28 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 27 Apr 2007 00:33:28 +0200 (CEST) Subject: [Python-checkins] r54989 - peps/trunk/pep-3119.txt peps/trunk/pep-3141.txt Message-ID: <20070426223328.12CD61E4003@bag.python.org> Author: guido.van.rossum Date: Fri Apr 27 00:33:22 2007 New Revision: 54989 Modified: peps/trunk/pep-3119.txt peps/trunk/pep-3141.txt Log: PEP 3141: Fix spelling of Transcendental. PEP 3119: Add overloading isinstance() and issubclass(); tighten invariant for Mapping.keys/values/items to use list(). Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Fri Apr 27 00:33:22 2007 @@ -20,6 +20,8 @@ can be used to define abstract methods. A class containing an abstract method that isn't overridden cannot be instantiated. +* A way to overload ``isinstance()`` and ``issubclass()``. + * Specific ABCs for containers and iterators, to be added to the collections module. @@ -124,6 +126,8 @@ * An "ABC support framework" which defines a built-in decorator that make it easy to define ABCs, and mechanisms to support it. +* A way to overload ``isinstance()`` and ``issubclass()``. + * Specific ABCs for containers and iterators, to be added to the collections module. @@ -180,6 +184,76 @@ cooperative multiple-inheritance [7]_, [8]_. +Overloading ``isinstance()`` and ``issubclass()`` +------------------------------------------------- + +During the development of this PEP and of its companion, PEP 3141, we +repeatedly faced the choice between standardizing more, fine-grained +ABCs or fewer, course-grained ones. For example, at one stage, PEP +3141 introduced the following stack of base classes used for complex +numbers: MonoidUnderPlus, AdditiveGroup, Ring, Field, Complex (each +derived from the previous). And the discussion mentioned several +other algebraic categorizations that were left out: Algebraic, +Transcendental, and IntegralDomain, and PrincipalIdealDomain. In this +PEP, we are wondering about the use cases for separate classes like +Set, ComposableSet, MutableSet, HashableSet, MutableComposableSet, +HashableComposableSet. + +The dilemma here is that we'd rather have fewer ABCs, but then what +should a user do who needs a less refined ABC? Consider e.g. the +plight of a mathematician who wants to define his own kind of +Transcendental numbers, but also wants float and int to be considered +Transcendental. PEP 3141 originally proposed to patch float.__bases__ +for that purpose, but there are some good reasons to keep the built-in +types immutable (for one, they are shared between all Python +interpreters running in the same address space, as is used by +mod_python). + +The solution proposed here is to allow overloading the built-in +functions ``isinstance()`` and ``issubclass()``. The overloading +works as follows: The call ``isinstance(x, C)`` first checks whether +``C.__instancecheck__`` exists, and if so, calls +``C.__subclasscheck__(x)`` instead of its normal implementation. +Similarly, the call ``issubclass(D, C)`` first checks whether +``C.__subclasscheck__`` exists, and if so, calls +``C.__subclasscheck__(D)`` instead of its normal implementation. + +Note that the magic names are not ``__isinstance__`` and +``__issubclass__``; this is because the reversal of the arguments +could cause confusion, especially for the ``issubclass()`` overloader. + +(We could also provide a default implementation of these that +implements the old algorithms; this would be more regular but would +have additional backwards compatibility issues, since the old +algorithms special-case objects not deriving from ``type`` in order to +support a different kind of overloading of these operations.) + +A prototype implementation of this is given in [12]_. + +Here is an example with (very simple) implementations of +``__instancecheck__`` and ``__subclasscheck__``:: + + assert issubclass(set, HashableSet) # Assume this is given + + class ABC: + + def __instancecheck__(cls, inst): + """Implement isinstance(inst, cls).""" + return any(cls.__subclasscheck__(c) + for c in {type(inst), inst.__class__}) + + def __subclasscheck__(cls, sub): + """Implement issubclass(sub, cls).""" + candidates = cls.__dict__.get("__subclass__", set()) | {cls} + return any(c in candidates for c in sub.mro()) + + class NoncomposableHashableSet(Set, Hashable, metaclass=ABC): + __subclass__ = {HashableSet} + + assert issubclass(set, NoncomposableHashableSet) + assert isinstance({1, 2, 3}, NoncomposableHashableSet) + + ABCs for Containers and Iterators --------------------------------- @@ -514,12 +588,10 @@ The following invariant should hold for any mapping ``m``:: - set(m.items()) == set(zip(m.keys(), m.values())) + list(m.items()) == list(zip(m.keys(), m.values())) - i.e. iterating over the keys and the values in parallel should - return *corresponding* keys and values. **Open issues:** Should - this always be required? How about the stronger invariant using - ``list()`` instead of ``set()``? + i.e. iterating over the items, keys and values should return + results in the same order. ``HashableMapping`` A subclass of ``Mapping`` and ``Hashable``. The values should be @@ -743,6 +815,9 @@ .. [11] Finite set, in Wikipedia (http://en.wikipedia.org/wiki/Finite_set) +.. [12] Make isinstance/issubclass overloadable + (http://python.org/sf/1708353) + Copyright ========= Modified: peps/trunk/pep-3141.txt ============================================================================== --- peps/trunk/pep-3141.txt (original) +++ peps/trunk/pep-3141.txt Fri Apr 27 00:33:22 2007 @@ -237,7 +237,7 @@ algebraic, but Python does define these operations on floats, which makes defining this class somewhat difficult. -``Trancendental`` +``Transcendental`` The elementary functions (http://en.wikipedia.org/wiki/Elementary_function) are defined. These are basically arbitrary powers, trig functions, and From buildbot at python.org Fri Apr 27 02:16:51 2007 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Apr 2007 00:16:51 +0000 Subject: [Python-checkins] buildbot warnings in alpha Tru64 5.1 2.5 Message-ID: <20070427001652.17C361E400B@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%25202.5/builds/250 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: barry.warsaw,collin.winter,georg.brandl,kristjan.jonsson,lars.gustaebel,neal.norwitz,raymond.hettinger,walter.doerwald Build had warnings: warnings failed slave lost sincerely, -The Buildbot From python-checkins at python.org Fri Apr 27 07:11:03 2007 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 27 Apr 2007 07:11:03 +0200 (CEST) Subject: [Python-checkins] r54990 - peps/trunk/pep-0000.txt peps/trunk/pep-3142.txt Message-ID: <20070427051103.F2A871E4004@bag.python.org> Author: martin.v.loewis Date: Fri Apr 27 07:11:00 2007 New Revision: 54990 Added: peps/trunk/pep-3142.txt (contents, props changed) Modified: peps/trunk/pep-0000.txt Log: Add PEP 3142. Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Fri Apr 27 07:11:00 2007 @@ -118,6 +118,7 @@ S 3118 Revising the buffer protocol Oliphant, Banks S 3119 Introducing Abstract Base Classes GvR, Talin S 3141 A Type Hierarchy for Numbers Yasskin + S 3142 Using UTF-8 as the default source encoding von L?wis Finished PEPs (done, implemented in Subversion) @@ -475,6 +476,7 @@ S 3118 Revising the buffer protocol Oliphant, Banks S 3119 Introducing Abstract Base Classes GvR, Talin S 3141 A Type Hierarchy for Numbers Yasskin + S 3142 Using UTF-8 as the default source encoding von L?wis Key Added: peps/trunk/pep-3142.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-3142.txt Fri Apr 27 07:11:00 2007 @@ -0,0 +1,107 @@ +PEP: 3142 +Title: Using UTF-8 as the default source encoding +Version: $Revision $ +Last-Modified: $Date $ +Author: Martin v. L?wis +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 15-Apr-2007 +Python-Version: 3.0 +Post-History: + + +Specification +============= + +This PEP proposes to change the default source encoding from ASCII to +UTF-8. Support for alternative source encodings [#pep263]_ continues to +exist; an explicit encoding declaration takes precedence over the +default. + + +A Bit of History +================ + +In Python 1, the source encoding was unspecified, except that the +source encoding had to be a superset of the system's basic execution +character set (i.e. an ASCII superset, on most systems). The source +encoding was only relevant for the lexis itself (bytes representing +letters for keywords, identifiers, punctuation, line breaks, etc). +The contents of a string literal was copied literally from the file +on source. + +In Python 2.0, the source encoding changed to Latin-1 as a side effect +of introducing Unicode. For Unicode string literals, the characters +were still copied literally from the source file, but widened on a +character-by-character basis. As Unicode gives a fixed interpretation +to code points, this algorithm effectively fixed a source encoding, at +least for files containing non-ASCII characters in Unicode literals. + +PEP 263 identified the problem that you can use only those Unicode +characters in a Unicode literal which are also in Latin-1, and +introduced a syntax for declaring the source encoding. If no source +encoding was given, the default should be ASCII. For compatibility +with Python 2.0 and 2.1, files were interpreted as Latin-1 for a +transitional period. This transition ended with Python 2.5, which +gives an error if non-ASCII characters are encountered and no source +encoding is declared. + +Rationale +========= + +With PEP 263, using arbitrary non-ASCII characters in a Python file is +possible, but tedious. One has to explicitly add an encoding +declaration. Even though some editors (like IDLE and Emacs) support +the declarations of PEP 263, many editors still do not (and never +will); users have to explicitly adjust the encoding which the editor +assumes on a file-by-file basis. + +When the default encoding is changed to UTF-8, adding non-ASCII text +to Python files becomes easier and more portable: On some systems, +editors will automatically choose UTF-8 when saving text (e.g. on Unix +systems where the locale uses UTF-8). On other systems, editors will +guess the encoding when reading the file, and UTF-8 is easy to +guess. Yet other editors support associating a default encoding with a +file extension, allowing users to associate .py with UTF-8. + +For Python 2, an important reason for using non-UTF-8 encodings was +that byte string literals would be in the source encoding at run-time, +allowing then to output them to a file or render them to the user +as-is. With Python 3, all strings will be Unicode strings, so the +original encoding of the source will have no impact at run-time. + +Implementation +============== + +The parser needs to be changed to accept bytes > 127 if no source +encoding is specified; instead of giving an error, it needs to check +that the bytes are well-formed UTF-8 (decoding is not necessary, +as the parser converts all source code to UTF-8, anyway). + +IDLE needs to be changed to use UTF-8 as the default encoding. + + +References +========== + +.. [#pep263] + http://www.python.org/dev/peps/pep-0263/ + + + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: From python-checkins at python.org Fri Apr 27 07:16:11 2007 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 27 Apr 2007 07:16:11 +0200 (CEST) Subject: [Python-checkins] r54991 - peps/trunk/pep-0000.txt peps/trunk/pep-3120.txt peps/trunk/pep-3142.txt Message-ID: <20070427051611.7269F1E4004@bag.python.org> Author: martin.v.loewis Date: Fri Apr 27 07:16:10 2007 New Revision: 54991 Added: peps/trunk/pep-3120.txt - copied, changed from r54990, peps/trunk/pep-3142.txt Removed: peps/trunk/pep-3142.txt Modified: peps/trunk/pep-0000.txt Log: Rename 3142 to 3120, as that is the next available number. Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Fri Apr 27 07:16:10 2007 @@ -117,8 +117,8 @@ S 3117 Postfix Type Declarations Brandl S 3118 Revising the buffer protocol Oliphant, Banks S 3119 Introducing Abstract Base Classes GvR, Talin + S 3120 Using UTF-8 as the default source encoding von L?wis S 3141 A Type Hierarchy for Numbers Yasskin - S 3142 Using UTF-8 as the default source encoding von L?wis Finished PEPs (done, implemented in Subversion) @@ -475,8 +475,8 @@ S 3117 Postfix Type Declarations Brandl S 3118 Revising the buffer protocol Oliphant, Banks S 3119 Introducing Abstract Base Classes GvR, Talin + S 3120 Using UTF-8 as the default source encoding von L?wis S 3141 A Type Hierarchy for Numbers Yasskin - S 3142 Using UTF-8 as the default source encoding von L?wis Key Copied: peps/trunk/pep-3120.txt (from r54990, peps/trunk/pep-3142.txt) ============================================================================== --- peps/trunk/pep-3142.txt (original) +++ peps/trunk/pep-3120.txt Fri Apr 27 07:16:10 2007 @@ -1,4 +1,4 @@ -PEP: 3142 +PEP: 3120 Title: Using UTF-8 as the default source encoding Version: $Revision $ Last-Modified: $Date $ Deleted: /peps/trunk/pep-3142.txt ============================================================================== --- /peps/trunk/pep-3142.txt Fri Apr 27 07:16:10 2007 +++ (empty file) @@ -1,107 +0,0 @@ -PEP: 3142 -Title: Using UTF-8 as the default source encoding -Version: $Revision $ -Last-Modified: $Date $ -Author: Martin v. L?wis -Status: Draft -Type: Standards Track -Content-Type: text/x-rst -Created: 15-Apr-2007 -Python-Version: 3.0 -Post-History: - - -Specification -============= - -This PEP proposes to change the default source encoding from ASCII to -UTF-8. Support for alternative source encodings [#pep263]_ continues to -exist; an explicit encoding declaration takes precedence over the -default. - - -A Bit of History -================ - -In Python 1, the source encoding was unspecified, except that the -source encoding had to be a superset of the system's basic execution -character set (i.e. an ASCII superset, on most systems). The source -encoding was only relevant for the lexis itself (bytes representing -letters for keywords, identifiers, punctuation, line breaks, etc). -The contents of a string literal was copied literally from the file -on source. - -In Python 2.0, the source encoding changed to Latin-1 as a side effect -of introducing Unicode. For Unicode string literals, the characters -were still copied literally from the source file, but widened on a -character-by-character basis. As Unicode gives a fixed interpretation -to code points, this algorithm effectively fixed a source encoding, at -least for files containing non-ASCII characters in Unicode literals. - -PEP 263 identified the problem that you can use only those Unicode -characters in a Unicode literal which are also in Latin-1, and -introduced a syntax for declaring the source encoding. If no source -encoding was given, the default should be ASCII. For compatibility -with Python 2.0 and 2.1, files were interpreted as Latin-1 for a -transitional period. This transition ended with Python 2.5, which -gives an error if non-ASCII characters are encountered and no source -encoding is declared. - -Rationale -========= - -With PEP 263, using arbitrary non-ASCII characters in a Python file is -possible, but tedious. One has to explicitly add an encoding -declaration. Even though some editors (like IDLE and Emacs) support -the declarations of PEP 263, many editors still do not (and never -will); users have to explicitly adjust the encoding which the editor -assumes on a file-by-file basis. - -When the default encoding is changed to UTF-8, adding non-ASCII text -to Python files becomes easier and more portable: On some systems, -editors will automatically choose UTF-8 when saving text (e.g. on Unix -systems where the locale uses UTF-8). On other systems, editors will -guess the encoding when reading the file, and UTF-8 is easy to -guess. Yet other editors support associating a default encoding with a -file extension, allowing users to associate .py with UTF-8. - -For Python 2, an important reason for using non-UTF-8 encodings was -that byte string literals would be in the source encoding at run-time, -allowing then to output them to a file or render them to the user -as-is. With Python 3, all strings will be Unicode strings, so the -original encoding of the source will have no impact at run-time. - -Implementation -============== - -The parser needs to be changed to accept bytes > 127 if no source -encoding is specified; instead of giving an error, it needs to check -that the bytes are well-formed UTF-8 (decoding is not necessary, -as the parser converts all source code to UTF-8, anyway). - -IDLE needs to be changed to use UTF-8 as the default encoding. - - -References -========== - -.. [#pep263] - http://www.python.org/dev/peps/pep-0263/ - - - -Copyright -========= - -This document has been placed in the public domain. - - - -.. - Local Variables: - mode: indented-text - indent-tabs-mode: nil - sentence-end-double-space: t - fill-column: 70 - coding: utf-8 - End: From python-checkins at python.org Fri Apr 27 07:52:34 2007 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 27 Apr 2007 07:52:34 +0200 (CEST) Subject: [Python-checkins] r54992 - peps/trunk/pep-3118.txt Message-ID: <20070427055234.917521E4004@bag.python.org> Author: martin.v.loewis Date: Fri Apr 27 07:52:31 2007 New Revision: 54992 Modified: peps/trunk/pep-3118.txt Log: Fix formatting problems. Modified: peps/trunk/pep-3118.txt ============================================================================== --- peps/trunk/pep-3118.txt (original) +++ peps/trunk/pep-3118.txt Fri Apr 27 07:52:31 2007 @@ -1,4 +1,3 @@ - PEP: 3118 Title: Revising the buffer protocol Version: $Revision$ @@ -192,7 +191,7 @@ This is the default flag state (0). The returned buffer may or may not have writeable memory. The format will be assumed to be unsigned bytes . This is a "stand-alone" flag constant. It never - needs to be |'d to the others. The exporter will raise an error if + needs to be \|'d to the others. The exporter will raise an error if it cannot provide such a contiguous buffer of bytes. PyBUF_REQ_WRITEABLE @@ -469,9 +468,8 @@ This is a C-API version of the getbuffer function call. It checks to make sure object has the required function pointer and issues the call. Returns -1 and raises an error on failure and returns 0 on -success. +success.:: -:: int PyObject_ReleaseBuffer(PyObject *obj, PyBuffer *view) This is a C-API version of the releasebuffer function call. It checks @@ -527,12 +525,12 @@ Methods: - lock - unlock - __getitem__ (will support multi-dimensional slicing) - __setitem__ (will support multi-dimensional slicing) - tobytes (obtain a bytes-object of everything in the memory). - tolist (obtain a "nested" list of the memory. Everything +| lock +| unlock +| __getitem__ (will support multi-dimensional slicing) +| __setitem__ (will support multi-dimensional slicing) +| tobytes (obtain a bytes-object of everything in the memory). +| tolist (obtain a "nested" list of the memory. Everything is interpreted into standard Python objects as the struct module unpack would do). @@ -600,9 +598,8 @@ Return 1 if the memory defined by the view object is C-style (fortran = 'C') or Fortran-style (fortran = 'F') contiguous or either one -(fortran = 'A'). Return 0 otherwise. +(fortran = 'A'). Return 0 otherwise.:: -:: int PyBuffer_IsAligned(PyBuffer *view); Return 1 if the memory at all elements of the array implied by the @@ -616,9 +613,8 @@ Fill the strides array with byte-strides of a contiguous (C-style if fortran is 0 or Fortran-style if fortran is 1) array of the given -shape with the given number of bytes per element. +shape with the given number of bytes per element.:: -:: int PyBuffer_FillInfo(PyBuffer *view, void *buf, Py_ssize_t len, int readonly, int infoflags) @@ -821,9 +817,7 @@ Ex. 1 ----------- -This example shows how an image object that uses contiguous lines might expose its buffer.:: - -:: +This example shows how an image object that uses contiguous lines might expose its buffer:: struct rgba { unsigned char r, g, b, a; @@ -847,8 +841,6 @@ So what does ImageObject's getbuffer do? Leaving error checking out:: -:: - int Image_getbuffer(PyObject *self, PyBuffer *view, int flags) { static Py_ssize_t suboffsets[2] = { -1, 0 }; @@ -899,9 +891,9 @@ return PyObject_FillBufferInfo(view, buf, len, readonly, flags); } -/* No releasebuffer is necessary because the memory will never -be re-allocated so the locking mechanism is not needed -*/ + /* No releasebuffer is necessary because the memory will never + be re-allocated so the locking mechanism is not needed + */ Ex. 3 ----------- From python-checkins at python.org Fri Apr 27 08:24:34 2007 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 27 Apr 2007 08:24:34 +0200 (CEST) Subject: [Python-checkins] r54993 - peps/trunk/pep-3120.txt Message-ID: <20070427062434.766801E4005@bag.python.org> Author: martin.v.loewis Date: Fri Apr 27 08:24:32 2007 New Revision: 54993 Modified: peps/trunk/pep-3120.txt (props changed) Log: Set svn:keywords. From python-checkins at python.org Fri Apr 27 08:34:40 2007 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 27 Apr 2007 08:34:40 +0200 (CEST) Subject: [Python-checkins] r54994 - peps/trunk/pep-3120.txt Message-ID: <20070427063440.AC0EA1E4004@bag.python.org> Author: martin.v.loewis Date: Fri Apr 27 08:34:37 2007 New Revision: 54994 Modified: peps/trunk/pep-3120.txt Log: Remove extra spaces. Modified: peps/trunk/pep-3120.txt ============================================================================== --- peps/trunk/pep-3120.txt (original) +++ peps/trunk/pep-3120.txt Fri Apr 27 08:34:37 2007 @@ -1,7 +1,7 @@ PEP: 3120 Title: Using UTF-8 as the default source encoding -Version: $Revision $ -Last-Modified: $Date $ +Version: $Revision$ +Last-Modified: $Date$ Author: Martin v. L?wis Status: Draft Type: Standards Track From python-checkins at python.org Fri Apr 27 08:45:37 2007 From: python-checkins at python.org (neal.norwitz) Date: Fri, 27 Apr 2007 08:45:37 +0200 (CEST) Subject: [Python-checkins] r54995 - python/trunk/Lib/test/test_pty.py Message-ID: <20070427064537.4F0271E4004@bag.python.org> Author: neal.norwitz Date: Fri Apr 27 08:45:32 2007 New Revision: 54995 Modified: python/trunk/Lib/test/test_pty.py Log: This gets the test working on Solaris. It seems a little hokey to me, but the test passed on Linux and Solaris, hopefully other platforms too. Modified: python/trunk/Lib/test/test_pty.py ============================================================================== --- python/trunk/Lib/test/test_pty.py (original) +++ python/trunk/Lib/test/test_pty.py Fri Apr 27 08:45:32 2007 @@ -1,3 +1,5 @@ +import errno +import fcntl import pty import os import sys @@ -40,6 +42,7 @@ # Marginal testing of pty suite. Cannot do extensive 'do or fail' testing # because pty code is not too portable. +# XXX(nnorwitz): these tests leak fds when there is an error. class PtyTest(unittest.TestCase): def setUp(self): # isatty() and close() can hang on some platforms. Set an alarm @@ -70,6 +73,22 @@ self.assertTrue(os.isatty(slave_fd), 'slave_fd is not a tty') + # Solaris requires reading the fd before anything is returned. + # My guess is that since we open and close the slave fd + # in master_open(), we need to read the EOF. + + # Ensure the fd is non-blocking in case there's nothing to read. + orig_flags = fcntl.fcntl(master_fd, fcntl.F_GETFL) + fcntl.fcntl(master_fd, fcntl.F_SETFL, orig_flags | os.O_NONBLOCK) + try: + s1 = os.read(master_fd, 1024) + self.assertEquals('', s1) + except OSError, e: + if e.errno != errno.EAGAIN: + raise + # Restore the original flags. + fcntl.fcntl(master_fd, fcntl.F_SETFL, orig_flags) + debug("Writing to slave_fd") os.write(slave_fd, TEST_STRING_1) s1 = os.read(master_fd, 1024) From python-checkins at python.org Fri Apr 27 08:58:35 2007 From: python-checkins at python.org (georg.brandl) Date: Fri, 27 Apr 2007 08:58:35 +0200 (CEST) Subject: [Python-checkins] r54996 - peps/trunk/pep-3118.txt Message-ID: <20070427065835.8B2A11E4004@bag.python.org> Author: georg.brandl Date: Fri Apr 27 08:58:33 2007 New Revision: 54996 Modified: peps/trunk/pep-3118.txt Log: Some reST sanitizing; change the Authors: header back to "Author:". Modified: peps/trunk/pep-3118.txt ============================================================================== --- peps/trunk/pep-3118.txt (original) +++ peps/trunk/pep-3118.txt Fri Apr 27 08:58:33 2007 @@ -2,7 +2,7 @@ Title: Revising the buffer protocol Version: $Revision$ Last-Modified: $Date$ -Authors: Travis Oliphant , Carl Banks +Author: Travis Oliphant , Carl Banks Status: Draft Type: Standards Track Content-Type: text/x-rst @@ -12,7 +12,7 @@ Abstract ======== -This PEP proposes re-designing the buffer interface (PyBufferProcs +This PEP proposes re-designing the buffer interface (``PyBufferProcs`` function pointers) to improve the way Python allows memory sharing in Python 3.0 @@ -87,7 +87,7 @@ libraries and because it is so simple it makes sense to support memory sharing using this model. The PIL memory model is sometimes used in C-code where a 2-d array can be then accessed using double - pointer indirection: e.g. image[i][j]. + pointer indirection: e.g. ``image[i][j]``. The buffer interface should allow the object to export either of these memory models. Consumers are free to either require contiguous memory @@ -139,26 +139,23 @@ to use the provided C-API to obtain a chunk of memory. -Change the PyBufferProcs structure to - -:: +Change the ``PyBufferProcs`` structure to :: typedef struct { getbufferproc bf_getbuffer; releasebufferproc bf_releasebuffer; - } - + } PyBufferProcs; :: typedef int (*getbufferproc)(PyObject *obj, PyBuffer *view, int flags) -This function returns 0 on success and -1 on failure (and raises an +This function returns ``0`` on success and ``-1`` on failure (and raises an error). The first variable is the "exporting" object. The second -argument is the address to a bufferinfo structure. If view is NULL, +argument is the address to a bufferinfo structure. If view is ``NULL``, then no information is returned but a lock on the memory is still obtained. In this case, the corresponding releasebuffer should also -be called with NULL. +be called with ``NULL``. The third argument indicates what kind of buffer the consumer is prepared to deal with and therefore what kind of buffer the exporter @@ -170,7 +167,7 @@ In addition, some exporters may not be able to share memory in every possible way and may need to raise errors to signal to some consumers that something is just not possible. These errors should be -PyErr_BufferError unless there is another error that is actually +``PyErr_BufferError`` unless there is another error that is actually causing the problem. The exporter can use flags information to simplify how much of the PyBuffer structure is filled in with non-default values and/or raise an error if the object can't support a @@ -183,10 +180,10 @@ segment, while others indicate to the exporter what kind of information the consumer can deal with. If certain information is not asked for by the consumer, but the exporter cannot share its memory -without that information, then a PyErr_BufferError should be raised. +without that information, then a ``PyErr_BufferError`` should be raised. -PyBUF_SIMPLE +``PyBUF_SIMPLE`` This is the default flag state (0). The returned buffer may or may not have writeable memory. The format will be assumed to be @@ -194,12 +191,12 @@ needs to be \|'d to the others. The exporter will raise an error if it cannot provide such a contiguous buffer of bytes. -PyBUF_REQ_WRITEABLE +``PyBUF_REQ_WRITEABLE`` The returned buffer must be writeable. If it is not writeable, then raise an error. -PyBUF_REQ_LOCKDATA +``PyBUF_REQ_LOCKDATA`` The returned buffer must be readonly. If the object is already read-only or it can make its memory read-only (and there are no @@ -207,28 +204,28 @@ buffer information. If the object does not have read-only memory (or cannot make it read-only), then an error should be raised. -PyBUF_REQ_FORMAT +``PyBUF_REQ_FORMAT`` The returned buffer must have true format information if this flag is provided. This would be used when the consumer is going to be checking for what 'kind' of data is actually stored. An exporter should always be able to provide this information if requested. If format is not explicitly requested then the format must be returned - as NULL (which means "B") + as ``NULL`` (which means "B") -PyBUF_REQ_ALIGNED (implies PyBUF_REQ_FORMAT) +``PyBUF_REQ_ALIGNED`` (implies ``PyBUF_REQ_FORMAT``) The returned buffer must have all (primitive data-type entries) aligned as the compiler would align them -PyBUF_ALW_ND +``PyBUF_ALW_ND`` The returned buffer must provide shape information. The memory will be assumed C-style contiguous (last dimension varies the fastest). The exporter may raise an error if it cannot provide this kind of contiguous buffer. -PyBUF_ALW_STRIDES (implies PyBUF_ALW_ND) +``PyBUF_ALW_STRIDES`` (implies ``PyBUF_ALW_ND``) The returned buffer must provide strides information. This would be used when the consumer can handle strided, discontiguous arrays. @@ -236,9 +233,9 @@ The exporter may raise an error if cannot provide a strided-only representation of the data (i.e. without the suboffsets). -PyBUF_REQ_C_CONTIGUOUS -PyBUF_REQ_F_CONTIGUOUS -PyBUF_REQ_ANY_CONTIGUOUS +| ``PyBUF_REQ_C_CONTIGUOUS`` +| ``PyBUF_REQ_F_CONTIGUOUS`` +| ``PyBUF_REQ_ANY_CONTIGUOUS`` These flags indicate that the returned buffer must be respectively, C-contiguous (last dimension varies the fastest), Fortran @@ -247,7 +244,7 @@ strides buffer info structure will be filled in correctly. -PyBUF_ALW_INDIRECT (implies PyBUF_ALW_STRIDES) +``PyBUF_ALW_INDIRECT`` (implies ``PyBUF_ALW_STRIDES``) The returned buffer must have suboffsets information. This would be used when the consumer can handle indirect array referencing @@ -258,34 +255,34 @@ Multi-dimensional (but contiguous) - PyBUF_CONTIG (PyBUF_ALW_ND | PyBUF_REQ_WRITEABLE | PyBUF_REQ_ALIGNED) - PyBUF_CONTIG_RO (PyBUF_ALW_ND | PyBUF_REQ_ALIGNED) - PyBUF_CONTIG_LCK (PyBUF_ALW_ND | PyBUF_REQ_LOCKDATA | PyBUF_REQ_ALIGNED) + | ``PyBUF_CONTIG`` (``PyBUF_ALW_ND | PyBUF_REQ_WRITEABLE | PyBUF_REQ_ALIGNED``) + | ``PyBUF_CONTIG_RO`` (``PyBUF_ALW_ND | PyBUF_REQ_ALIGNED``) + | ``PyBUF_CONTIG_LCK`` (``PyBUF_ALW_ND | PyBUF_REQ_LOCKDATA | PyBUF_REQ_ALIGNED``) Multi-dimensional using strides but aligned - PyBUF_STRIDED (PyBUF_ALW_STRIDES | PyBUF_REQ_WRITEABLE | PyBUF_REQ_ALIGNED) - PyBUF_STRIDED_RO (PyBUF_ALW_STRIDES | PyBUF_REQ_ALIGNED) - PyBUF_STRIDED_LCK (PyBUF_ALW_STRIDES | PyBUF_REQ_LOCKDATA | PyBUF_REQ_ALIGNED) + | ``PyBUF_STRIDED`` (``PyBUF_ALW_STRIDES | PyBUF_REQ_WRITEABLE | PyBUF_REQ_ALIGNED``) + | ``PyBUF_STRIDED_RO`` (``PyBUF_ALW_STRIDES | PyBUF_REQ_ALIGNED``) + | ``PyBUF_STRIDED_LCK`` (``PyBUF_ALW_STRIDES | PyBUF_REQ_LOCKDATA | PyBUF_REQ_ALIGNED``) Multi-dimensional using strides and not necessarily aligned - PyBUF_RECORDS (PyBUF_ALW_STRIDES | PyBUF_REQ_WRITEABLE | PyBUF_REQ_FORMAT) - PyBUF_RECORDS_RO (PyBUF_ALW_STRIDES | PyBUF_REQ_FORMAT) - PyBUF_RECORDS_LCK (PyBUF_ALW_STRIDES | PyBUF_REQ_LOCKDATA | PyBUF_REQ_FORMAT) + | ``PyBUF_RECORDS`` (``PyBUF_ALW_STRIDES | PyBUF_REQ_WRITEABLE | PyBUF_REQ_FORMAT``) + | ``PyBUF_RECORDS_RO`` (``PyBUF_ALW_STRIDES | PyBUF_REQ_FORMAT``) + | ``PyBUF_RECORDS_LCK`` (``PyBUF_ALW_STRIDES | PyBUF_REQ_LOCKDATA | PyBUF_REQ_FORMAT``) Multi-dimensional using sub-offsets - PyBUF_FULL (PyBUF_ALW_INDIRECT | PyBUF_REQ_WRITEABLE | PyBUF_REQ_FORMAT) - PyBUF_FULL_RO (PyBUF_ALW_INDIRECT | PyBUF_REQ_FORMAT) - PyBUF_FULL_LCK (PyBUF_ALW_INDIRECT | PyBUF_REQ_LOCKDATA | PyBUF_REQ_FORMAT) + | ``PyBUF_FULL`` (``PyBUF_ALW_INDIRECT | PyBUF_REQ_WRITEABLE | PyBUF_REQ_FORMAT``) + | ``PyBUF_FULL_RO`` (``PyBUF_ALW_INDIRECT | PyBUF_REQ_FORMAT``) + | ``PyBUF_FULL_LCK`` (``PyBUF_ALW_INDIRECT | PyBUF_REQ_LOCKDATA | PyBUF_REQ_FORMAT``) Thus, the consumer simply wanting a contiguous chunk of bytes from -the object would use PyBUF_SIMPLE, while a consumer that understands -how to make use of the most complicated cases could use PyBUF_FULL +the object would use ``PyBUF_SIMPLE``, while a consumer that understands +how to make use of the most complicated cases could use ``PyBUF_FULL``. The format information is only guaranteed to be non-NULL if -PyBUF_REQ_FORMAT is in the flag argument, otherwise it is expected the +``PyBUF_REQ_FORMAT`` is in the flag argument, otherwise it is expected the consumer will assume unsigned bytes. There is a C-API that simple exporting objects can use to fill-in the @@ -319,15 +316,15 @@ The members of the bufferinfo structure are: -buf +``buf`` a pointer to the start of the memory for the object -len +``len`` the total bytes of memory the object uses. This should be the same as the product of the shape array multiplied by the number of bytes per item of memory. -readonly +``readonly`` an integer variable to hold whether or not the memory is readonly. 1 means the memory is readonly, zero means the memory is writeable, and -1 means the memory was "locked" (changed from @@ -335,33 +332,33 @@ and therefore should be unlocked when this PyBuffer structure is "released" (this is supported only by some exporters). -format +``format`` a NULL-terminated format-string (following the struct-style syntax including extensions) indicating what is in each element of memory. The number of elements is len / itemsize, where itemsize is the number of bytes implied by the format. This can be NULL which implies standard unsigned bytes ("B"). -ndims +``ndims`` a variable storing the number of dimensions the memory represents. Must be >=0. A value of 0 means that shape and strides and suboffsets - must be NULL (i.e. the memory represents a scalar). + must be ``NULL`` (i.e. the memory represents a scalar). -shape +``shape`` an array of ``Py_ssize_t`` of length ``ndims`` indicating the shape of the memory as an N-D array. Note that ``((*shape)[0] * ... * (*shape)[ndims-1])*itemsize = len``. If ndims is 0 (indicating - a scalar), then this must be NULL. + a scalar), then this must be ``NULL``. -strides +``strides`` address of a ``Py_ssize_t*`` variable that will be filled with a - pointer to an array of ``Py_ssize_t`` of length ``ndims`` (or NULL - if ndims is 0). indicating the number of bytes to skip to get to + pointer to an array of ``Py_ssize_t`` of length ``ndims`` (or ``NULL`` + if ``ndims`` is 0). indicating the number of bytes to skip to get to the next element in each dimension. If this is not requested by - the caller (PyBUF_ALW_STRIDES is not set), then this should be set + the caller (``PyBUF_ALW_STRIDES`` is not set), then this should be set to NULL which indicates a C-style contiguous array. -suboffsets +``suboffsets`` address of a ``Py_ssize_t *`` variable that will be filled with a pointer to an array of ``Py_ssize_t`` of length ``*ndims``. If these suboffset numbers are >=0, then the value stored along the @@ -374,14 +371,14 @@ For clarity, here is a function that returns a pointer to the element in an N-D array pointed to by an N-dimesional index when - there are both non-NULL strides and suboffsets.:: + there are both non-NULL strides and suboffsets:: - void* get_item_pointer(int ndim, void* buf, Py_ssize_t* strides, - Py_ssize_t* suboffsets, Py_ssize_t *indices) { - char* pointer = (char*)buf; + void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides, + Py_ssize_t *suboffsets, Py_ssize_t *indices) { + char *pointer = (char*)buf; int i; for (i = 0; i < ndim; i++) { - pointer += strides[i]*indices[i]; + pointer += strides[i] * indices[i]; if (suboffsets[i] >=0 ) { pointer = *((char**)pointer) + suboffsets[i]; } @@ -395,15 +392,15 @@ the location of the starting pointer directly (i.e. buf would be modified). -itemsize +``itemsize`` This is a storage for the itemsize of each element of the shared memory. It is strictly un-necessary as it can be obtained using - PyBuffer_SizeFromFormat, however an exporter may know this + ``PyBuffer_SizeFromFormat``, however an exporter may know this information without parsing the format string and it is necessary to know the itemsize for proper interpretation of striding. Therefore, storing it is more convenient and faster. -internal +``internal`` This is for use internally by the exporting object. For example, this might be re-cast as an integer by the exporter and used to store flags about whether or not the shape, strides, and suboffsets @@ -468,7 +465,9 @@ This is a C-API version of the getbuffer function call. It checks to make sure object has the required function pointer and issues the call. Returns -1 and raises an error on failure and returns 0 on -success.:: +success. + +:: int PyObject_ReleaseBuffer(PyObject *obj, PyBuffer *view) @@ -486,9 +485,7 @@ A memory-view object is an extended buffer object that could replace the buffer object (but doesn't have to as that could be kept as a -simple 1-d memory-view object). It's C-structure is - -:: +simple 1-d memory-view object). Its C-structure is :: typedef struct { PyObject_HEAD @@ -521,29 +518,29 @@ The Python name will be -__builtin__.memory +``__builtin__.memory`` Methods: -| lock -| unlock -| __getitem__ (will support multi-dimensional slicing) -| __setitem__ (will support multi-dimensional slicing) -| tobytes (obtain a bytes-object of everything in the memory). -| tolist (obtain a "nested" list of the memory. Everything - is interpreted into standard Python objects - as the struct module unpack would do). - -Attributes (taken from the memory of the base object) - - format - itemsize - shape - strides - suboffsets - size - readonly - ndim +| ``lock`` +| ``unlock`` +| ``__getitem__`` (will support multi-dimensional slicing) +| ``__setitem__`` (will support multi-dimensional slicing) +| ``tobytes`` (obtain a bytes-object of everything in the memory). +| ``tolist`` (obtain a "nested" list of the memory. Everything + is interpreted into standard Python objects + as the struct module unpack would do). + +Attributes (taken from the memory of the base object): + +* ``format`` +* ``itemsize`` +* ``shape`` +* ``strides`` +* ``suboffsets`` +* ``size`` +* ``readonly`` +* ``ndim`` :: @@ -594,13 +591,15 @@ :: - int PyBuffer_IsContiguous(PyBuffer *view, char fortran); + int PyBuffer_IsContiguous(PyBuffer *view, char fortran) Return 1 if the memory defined by the view object is C-style (fortran = 'C') or Fortran-style (fortran = 'F') contiguous or either one -(fortran = 'A'). Return 0 otherwise.:: +(fortran = 'A'). Return 0 otherwise. + +:: - int PyBuffer_IsAligned(PyBuffer *view); + int PyBuffer_IsAligned(PyBuffer *view) Return 1 if the memory at all elements of the array implied by the view object is aligned @@ -613,7 +612,9 @@ Fill the strides array with byte-strides of a contiguous (C-style if fortran is 0 or Fortran-style if fortran is 1) array of the given -shape with the given number of bytes per element.:: +shape with the given number of bytes per element. + +:: int PyBuffer_FillInfo(PyBuffer *view, void *buf, Py_ssize_t len, int readonly, int infoflags) @@ -623,7 +624,8 @@ given length. Returns 0 on success and -1 (with raising an error) on error. -:: +:: + PyErr_BufferError A new error object for returning buffer errors which arise because an @@ -638,7 +640,7 @@ The struct string-syntax is missing some characters to fully implement data-format descriptions already available elsewhere (in ctypes and NumPy for example). The Python 2.5 specification is -at http://docs.python.org/lib/module-struct.html +at http://docs.python.org/lib/module-struct.html. Here are the proposed additions: @@ -682,11 +684,11 @@ previously-specified endian string is in force until changed. The default endian is '@' which means native data-types and alignment. If un-aligned, native data-types are requested, then the endian -specification is '^'. +specification is '^'. According to the struct-module, a number can preceed a character code to specify how many of that type there are. The -(k1,k2,...,kn) extension also allows specifying if the data is +``(k1,k2,...,kn)`` extension also allows specifying if the data is supposed to be viewed as a (C-style contiguous, last-dimension varies the fastest) multi-dimensional array of a particular format. @@ -702,15 +704,15 @@ is the constructor for a named-tuple (not-specified yet). float - 'f' <--> Python float + ``'f'`` <--> Python float complex double - 'Zd' <--> Python complex + ``'Zd'`` <--> Python complex RGB Pixel data - 'BBB' <--> (int, int, int) - 'B:r: B:g: B:b:' <--> ((int, int, int), ('r','g','b')) + ``'BBB'`` <--> (int, int, int) + ``'B:r: B:g: B:b:'`` <--> ((int, int, int), ('r','g','b')) Mixed endian (weird but possible) - '>i:big: ((int, int), ('big', 'little')) + ``'>i:big: ((int, int), ('big', 'little')) Nested structure :: @@ -802,8 +804,9 @@ call more difficult. The flags variable allows the same ability of consumers to be "simple" in how they call the protocol. + Code -======== +==== The authors of the PEP promise to contribute and maintain the code for this proposal but will welcome any help. @@ -812,7 +815,7 @@ Examples -========= +======== Ex. 1 ----------- @@ -834,8 +837,8 @@ Py_ssize_t view_count; }; -"lines" points to malloced 1-D array of (struct rgba*). Each pointer -in THAT block points to a seperately malloced array of (struct rgba). +"lines" points to malloced 1-D array of ``(struct rgba*)``. Each pointer +in THAT block points to a seperately malloced array of ``(struct rgba)``. In order to access, say, the red value of the pixel at x=30, y=50, you'd use "lines[50][30].r". @@ -957,5 +960,5 @@ Copyright ========= -This PEP is placed in the public domain +This PEP is placed in the public domain. From buildbot at python.org Fri Apr 27 09:07:38 2007 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Apr 2007 07:07:38 +0000 Subject: [Python-checkins] buildbot warnings in amd64 gentoo trunk Message-ID: <20070427070738.F302C1E4004@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo trunk. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%2520gentoo%2520trunk/builds/1986 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: neal.norwitz Build had warnings: warnings test Excerpt from the test logfile: Traceback (most recent call last): File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_socketserver.py", line 93, in run svr.serve_a_few() File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_socketserver.py", line 35, in serve_a_few self.handle_request() File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/SocketServer.py", line 224, in handle_request self.handle_error(request, client_address) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/SocketServer.py", line 222, in handle_request self.process_request(request, client_address) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/SocketServer.py", line 429, in process_request self.collect_children() File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/SocketServer.py", line 425, in collect_children self.active_children.remove(pid) ValueError: list.remove(x): x not in list make: *** [buildbottest] Segmentation fault (core dumped) sincerely, -The Buildbot From python-checkins at python.org Fri Apr 27 10:27:25 2007 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 27 Apr 2007 10:27:25 +0200 (CEST) Subject: [Python-checkins] r54997 - peps/trunk/pep-0000.txt peps/trunk/pep-3121.txt Message-ID: <20070427082725.ADDE91E4004@bag.python.org> Author: martin.v.loewis Date: Fri Apr 27 10:27:24 2007 New Revision: 54997 Added: peps/trunk/pep-3121.txt (contents, props changed) Modified: peps/trunk/pep-0000.txt Log: Add PEP 3121. Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Fri Apr 27 10:27:24 2007 @@ -118,6 +118,7 @@ S 3118 Revising the buffer protocol Oliphant, Banks S 3119 Introducing Abstract Base Classes GvR, Talin S 3120 Using UTF-8 as the default source encoding von L?wis + S 3121 Module Initialization and finalization von L?wis S 3141 A Type Hierarchy for Numbers Yasskin Finished PEPs (done, implemented in Subversion) @@ -476,6 +477,7 @@ S 3118 Revising the buffer protocol Oliphant, Banks S 3119 Introducing Abstract Base Classes GvR, Talin S 3120 Using UTF-8 as the default source encoding von L?wis + S 3121 Module Initialization and finalization von L?wis S 3141 A Type Hierarchy for Numbers Yasskin Added: peps/trunk/pep-3121.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-3121.txt Fri Apr 27 10:27:24 2007 @@ -0,0 +1,220 @@ +PEP: 3121 +Title: Module Initialization and finalization +Version: $Revision: 54994 $ +Last-Modified: $Date: 2007-04-27 08:34:37 +0200 (Fr, 27 Apr 2007) $ +Author: Martin v. L?wis +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 27-Apr-2007 +Python-Version: 3.0 +Post-History: + +Abstract +======== + +Module initialization currently has a few deficiencies. There is no +cleanup for modules, the entry point name might give naming conflicts, +the entry functions don't follow the usual calling convention, and +multiple interpreters are not supported well. This PEP addresses these +issues. + +Module Finalization +=================== + +Currently, C modules are initialized usually once and then "live" +forever. The only exception is when Py_Finalize() is called: then +the initialization routine is invoked a second time. This is bad +from a resource management point of view: memory and other resources +might get allocated each time initialization is called, but there +is no way to reclaim them. As a result, there is currently no +way to completely release all resources Python has allocated. + +Entry point name conflicts +========================== + +The entry point is currently called init. This might conflict +with other symbols also called init. In particular, +initsocket is known to have conflicted in the past (this specific +problem got resolved as a side effect of renaming the module to +_socket). + +Entry point signature +===================== + +The entry point is currently a procedure (returning void). This +deviates from the usual calling conventions; callers can find out +whether there was an error during initialization only by checking +PyErr_Occurred. The entry point should return a PyObject*, which will +be the module created, or NULL in case of an exception. + +Multiple Interpreters +===================== + +Currently, extension modules share their state across all +interpreters. This allows for undesirable information leakage across +interpreters: one script could permanently corrupt objects in an +extension module, possibly breaking all scripts in other interpreters. + +Specification +============= + +The module initialization routines change their signature +to:: + + PyObject *PyInit_() + +The initialization routine will be invoked once per +interpreter, when the module is imported. It should +return a new module object each time. + +In order to store per-module state in C variables, +each module object will contain a block of memory +that is interpreted only by the module. The amount +of memory used for the module is specified at +the point of creation of the module. + +In addition to the initialization function, a module +may implement a number of additional callback +function, which are invoked when the module's +tp_traverse, tp_clear, and tp_free functions are +invoked, and when the module is reloaded. + +The entire module definition is combined in a struct +PyModuleDef:: + + struct PyModuleDef{ + PyModuleDef_Base m_base; /* To be filled out by the interpreter */ + Py_ssize_t m_size; /* Size of per-module data */ + PyMethodDef *m_methods; + inquiry m_reload; + traverseproc m_traverse; + inquiry m_clear; + freefunc m_free; + }; + +Creation of a module is changed to expect an optional +PyModuleDef*. The module state will be +null-initialized. + +Each module method with be passed the module object +as the first parameter. To access the module data, +a function:: + + void* PyModule_GetData(PyObject*); + +will be provided. In addition, to lookup a module +more efficiently than going through sys.modules, +a function:: + + PyObject* PyState_FindModule(struct PyModuleDef*); + +will be provided. This lookup function will use an +index located in the m_base field, to find the +module by index, not by name. + +As all Python objects should be controlled through +the Python memory management, usage of "static" +type objects is discouraged, unless the type object +itself has no memory-managed state. To simplify +definition of heap types, a new method:: + + PyTypeObject* PyType_Copy(PyTypeObject*); + +is added. + +Example +======= + +xxmodule.c would be changed to remove the initxx +function, and add the following code instead:: + + struct xxstate{ + PyObject *ErrorObject; + PyObject *Xxo_Type; + }; + + #define xxstate(o) ((struct xxstate*)PyModule_GetState(o)) + + static int xx_traverse(PyObject *m, visitproc v, + void *arg) + { + Py_VISIT(xxstate(m)->ErrorObject); + Py_VISIT(xxstate(m)->Xxo_Type); + return 0; + } + + static int xx_clear(PyObject *m) + { + Py_CLEAR(xxstate(m)->ErrorObject); + Py_CLEAR(xxstate(m)->Xxo_Type); + return 0; + } + + static struct PyModuleDef xxmodule = { + {}, /* m_base */ + sizeof(struct xxstate), + &xx_methods, + 0, /* m_reload */ + xx_traverse, + xx_clear, + 0, /* m_free - not needed, since all is done in m_clear */ + } + + PyObject* + PyInit_xx() + { + PyObject *res = PyModule_New("xx", &xxmodule); + if (!res) return NULL; + xxstate(res)->ErrorObject = PyErr_NewException("xx.error, NULL, NULL); + if (!xxstate(res)->ErrorObject) { + Py_DECREF(res); + return NULL; + } + xxstate(res)->XxoType = PyType_Copy(&Xxo_Type); + if (!xxstate(res)->Xxo_Type) { + Py_DECREF(res); + return NULL; + } + return res; + } + + +Discussion +========== + +Tim Peters reports in [1]_ that PythonLabs considered such a feature +at one point, and lists the following additional hooks which aren't +currently supported in this PEP: + + * when the module object is deleted from sys.modules + + * when Py_Finalize is called + + * when Python exits + + * when the Python DLL is unloaded (Windows only) + + +References +========== + +.. [1] Tim Peters, reporting earlier conversation about such a feature + http://mail.python.org/pipermail/python-3000/2006-April/000726.html + + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: From python-checkins at python.org Fri Apr 27 10:32:02 2007 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 27 Apr 2007 10:32:02 +0200 (CEST) Subject: [Python-checkins] r54998 - peps/trunk/pep-3121.txt Message-ID: <20070427083202.C2B1B1E401A@bag.python.org> Author: martin.v.loewis Date: Fri Apr 27 10:31:58 2007 New Revision: 54998 Modified: peps/trunk/pep-3121.txt (contents, props changed) Log: Add keywords for PEP 3121. Modified: peps/trunk/pep-3121.txt ============================================================================== --- peps/trunk/pep-3121.txt (original) +++ peps/trunk/pep-3121.txt Fri Apr 27 10:31:58 2007 @@ -1,7 +1,7 @@ PEP: 3121 Title: Module Initialization and finalization -Version: $Revision: 54994 $ -Last-Modified: $Date: 2007-04-27 08:34:37 +0200 (Fr, 27 Apr 2007) $ +Version: $Revision$ +Last-Modified: $Date$ Author: Martin v. L?wis Status: Draft Type: Standards Track From barry at python.org Fri Apr 27 17:10:16 2007 From: barry at python.org (Barry Warsaw) Date: Fri, 27 Apr 2007 11:10:16 -0400 Subject: [Python-checkins] r54995 - python/trunk/Lib/test/test_pty.py In-Reply-To: <20070427064537.4F0271E4004@bag.python.org> References: <20070427064537.4F0271E4004@bag.python.org> Message-ID: <13962851-41C0-46C9-B12A-55459796226D@python.org> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Apr 27, 2007, at 2:45 AM, neal.norwitz wrote: > Author: neal.norwitz > Date: Fri Apr 27 08:45:32 2007 > New Revision: 54995 > > Modified: > python/trunk/Lib/test/test_pty.py > Log: > This gets the test working on Solaris. It seems a little hokey to me, > but the test passed on Linux and Solaris, hopefully other platforms > too. Seems fine on OS X 10.4.9 too. - -Barry -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Darwin) iQCVAwUBRjISWHEjvBPtnXfVAQKIzwQAsfAnsXeppa+TX9AlTVgZ5bFfREuD8EHK 4yzu811vIKffYXMmHsLEXOiJz/etxJWF3Ho+IG72Twf3MVY8/8Ly96mYI9l8KQCQ pcVP+Q7UT9ZhA632BpFLDDJuf0e8v2Nn8avSQZKu1X4CfEyNvp2OridrJd5xnhjG R1XYWgdxa+0= =PQwc -----END PGP SIGNATURE----- From python-checkins at python.org Fri Apr 27 18:20:40 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 27 Apr 2007 18:20:40 +0200 (CEST) Subject: [Python-checkins] r54999 - sandbox/trunk/2to3/fixes/fix_next.py Message-ID: <20070427162040.6F52E1E4005@bag.python.org> Author: guido.van.rossum Date: Fri Apr 27 18:20:39 2007 New Revision: 54999 Modified: sandbox/trunk/2to3/fixes/fix_next.py Log: Add clone() method to DelayedStrNode class; it may be called. Modified: sandbox/trunk/2to3/fixes/fix_next.py ============================================================================== --- sandbox/trunk/2to3/fixes/fix_next.py (original) +++ sandbox/trunk/2to3/fixes/fix_next.py Fri Apr 27 18:20:39 2007 @@ -14,14 +14,16 @@ bind_warning = "Calls to builtin next() possibly shadowed by global binding" + class DelayedStrNode(object): + def __init__(self, type, base): self.parent = None self.shadowed_next = False self.base = base self.type = type self.value = "" - + def __str__(self): b = "".join([str(n) for n in self.base]) if self.shadowed_next: @@ -29,6 +31,13 @@ else: return "next(%s)" % b + def clone(self): + node = DelayedStrNode(self.type, self.base) + node.shadowed_next = self.shadowed_next + node.value = self.value + return node + + class FixNext(basefix.BaseFix): PATTERN = """ power< base=any+ trailer< '.' 'next' > trailer< '(' ')' > > From python-checkins at python.org Fri Apr 27 18:46:00 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 27 Apr 2007 18:46:00 +0200 (CEST) Subject: [Python-checkins] r55000 - sandbox/trunk/2to3/refactor.py Message-ID: <20070427164600.A06971E4006@bag.python.org> Author: guido.van.rossum Date: Fri Apr 27 18:45:58 2007 New Revision: 55000 Modified: sandbox/trunk/2to3/refactor.py Log: After replacing 'node' with 'new' in the tree, also move 'new' into the local variable 'node', so a second firing transformation won't hit an assertion. Modified: sandbox/trunk/2to3/refactor.py ============================================================================== --- sandbox/trunk/2to3/refactor.py (original) +++ sandbox/trunk/2to3/refactor.py Fri Apr 27 18:45:58 2007 @@ -259,6 +259,7 @@ if new is not None and (new != node or str(new) != str(node)): node.replace(new) + node = new changes += 1 elif tree.was_changed: changes += 1 From python-checkins at python.org Fri Apr 27 21:19:36 2007 From: python-checkins at python.org (georg.brandl) Date: Fri, 27 Apr 2007 21:19:36 +0200 (CEST) Subject: [Python-checkins] r55001 - python/branches/release25-maint/Doc/tut/tut.tex Message-ID: <20070427191936.E79251E4006@bag.python.org> Author: georg.brandl Date: Fri Apr 27 21:19:29 2007 New Revision: 55001 Modified: python/branches/release25-maint/Doc/tut/tut.tex Log: Version fix (bug #1708710) Modified: python/branches/release25-maint/Doc/tut/tut.tex ============================================================================== --- python/branches/release25-maint/Doc/tut/tut.tex (original) +++ python/branches/release25-maint/Doc/tut/tut.tex Fri Apr 27 21:19:29 2007 @@ -184,12 +184,12 @@ \file{/usr/local/python} is a popular alternative location.) On Windows machines, the Python installation is usually placed in -\file{C:\e Python24}, though you can change this when you're running +\file{C:\e Python25}, though you can change this when you're running the installer. To add this directory to your path, you can type the following command into the command prompt in a DOS box: \begin{verbatim} -set path=%path%;C:\python24 +set path=%path%;C:\python25 \end{verbatim} @@ -4654,7 +4654,7 @@ >>> os.system('time 0:02') 0 >>> os.getcwd() # Return the current working directory -'C:\\Python24' +'C:\\Python25' >>> os.chdir('/server/accesslogs') \end{verbatim} @@ -5254,7 +5254,7 @@ Traceback (most recent call last): File "", line 1, in -toplevel- d['primary'] # entry was automatically removed - File "C:/PY24/lib/weakref.py", line 46, in __getitem__ + File "C:/python25/lib/weakref.py", line 46, in __getitem__ o = self.data[key]() KeyError: 'primary' \end{verbatim} From python-checkins at python.org Fri Apr 27 21:20:01 2007 From: python-checkins at python.org (georg.brandl) Date: Fri, 27 Apr 2007 21:20:01 +0200 (CEST) Subject: [Python-checkins] r55002 - python/trunk/Doc/tut/tut.tex Message-ID: <20070427192001.C1E461E4006@bag.python.org> Author: georg.brandl Date: Fri Apr 27 21:20:00 2007 New Revision: 55002 Modified: python/trunk/Doc/tut/tut.tex Log: Version fix (bug #1708710) Modified: python/trunk/Doc/tut/tut.tex ============================================================================== --- python/trunk/Doc/tut/tut.tex (original) +++ python/trunk/Doc/tut/tut.tex Fri Apr 27 21:20:00 2007 @@ -184,12 +184,12 @@ \file{/usr/local/python} is a popular alternative location.) On Windows machines, the Python installation is usually placed in -\file{C:\e Python24}, though you can change this when you're running +\file{C:\e Python26}, though you can change this when you're running the installer. To add this directory to your path, you can type the following command into the command prompt in a DOS box: \begin{verbatim} -set path=%path%;C:\python24 +set path=%path%;C:\python26 \end{verbatim} @@ -4654,7 +4654,7 @@ >>> os.system('time 0:02') 0 >>> os.getcwd() # Return the current working directory -'C:\\Python24' +'C:\\Python26' >>> os.chdir('/server/accesslogs') \end{verbatim} @@ -5254,7 +5254,7 @@ Traceback (most recent call last): File "", line 1, in -toplevel- d['primary'] # entry was automatically removed - File "C:/PY24/lib/weakref.py", line 46, in __getitem__ + File "C:/python26/lib/weakref.py", line 46, in __getitem__ o = self.data[key]() KeyError: 'primary' \end{verbatim} From python-checkins at python.org Fri Apr 27 21:55:27 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 27 Apr 2007 21:55:27 +0200 (CEST) Subject: [Python-checkins] r55005 - in python/branches/p3yk: Demo/parser/unparse.py Doc/api/abstract.tex Doc/api/concrete.tex Doc/api/init.tex Doc/api/memory.tex Doc/api/newtypes.tex Doc/api/utilities.tex Doc/commontex/copyright.tex Doc/commontex/license.tex Doc/dist/dist.tex Doc/ext/newtypes.tex Doc/ext/shoddy.c Doc/inst/inst.tex Doc/lib/compiler.tex Doc/lib/email.tex Doc/lib/emailutil.tex Doc/lib/libamoeba.tex Doc/lib/libasyncore.tex Doc/lib/libbsddb.tex Doc/lib/libcfgparser.tex Doc/lib/libcgitb.tex Doc/lib/libcmath.tex Doc/lib/libcmd.tex Doc/lib/libcode.tex Doc/lib/libcodecs.tex Doc/lib/libcollections.tex Doc/lib/libcommands.tex Doc/lib/libconsts.tex Doc/lib/libcookielib.tex Doc/lib/libctypes.tex Doc/lib/libcurses.tex Doc/lib/libcursespanel.tex Doc/lib/libdatetime.tex Doc/lib/libdbhash.tex Doc/lib/libdecimal.tex Doc/lib/libdl.tex Doc/lib/libdoctest.tex Doc/lib/libdocxmlrpc.tex Doc/lib/libdumbdbm.tex Doc/lib/libetree.tex Doc/lib/libfm.tex Doc/lib/libfnmatch.tex Doc/lib/libftplib.tex Doc/lib/libfuncs.tex Doc/lib/libgettext.tex Doc/lib/libhmac.tex Doc/lib/libhotshot.tex Doc/lib/libhtmllib.tex Doc/lib/libhtmlparser.tex Doc/lib/libhttplib.tex Doc/lib/libimaplib.tex Doc/lib/liblogging.tex Doc/lib/libmailbox.tex Doc/lib/libmimetools.tex Doc/lib/libmimetypes.tex Doc/lib/libmimewriter.tex Doc/lib/libmmap.tex Doc/lib/libmsilib.tex Doc/lib/libmultifile.tex Doc/lib/libmutex.tex Doc/lib/libnetrc.tex Doc/lib/libnntplib.tex Doc/lib/liboptparse.tex Doc/lib/libos.tex Doc/lib/libpdb.tex Doc/lib/libpipes.tex Doc/lib/libplatform.tex Doc/lib/libpopen2.tex Doc/lib/libpoplib.tex Doc/lib/libposixfile.tex Doc/lib/libposixpath.tex Doc/lib/libpprint.tex Doc/lib/libqueue.tex Doc/lib/libre.tex Doc/lib/librepr.tex Doc/lib/librexec.tex Doc/lib/librfc822.tex Doc/lib/libsched.tex Doc/lib/libselect.tex Doc/lib/libshlex.tex Doc/lib/libshutil.tex Doc/lib/libsimplexmlrpc.tex Doc/lib/libsite.tex Doc/lib/libsmtplib.tex Doc/lib/libsocket.tex Doc/lib/libsqlite3.tex Doc/lib/libstdtypes.tex Doc/lib/libstring.tex Doc/lib/libsubprocess.tex Doc/lib/libsun.tex Doc/lib/libsys.tex Doc/lib/libtarfile.tex Doc/lib/libtelnetlib.tex Doc/lib/libtempfile.tex Doc/lib/libtest.tex Doc/lib/libtextwrap.tex Doc/lib/libthreading.tex Doc/lib/libtimeit.tex Doc/lib/libturtle.tex Doc/lib/libunittest.tex Doc/lib/liburllib2.tex Doc/lib/liburlparse.tex Doc/lib/libwebbrowser.tex Doc/lib/libwinreg.tex Doc/lib/libxmlrpclib.tex Doc/lib/libzipfile.tex Doc/lib/libzlib.tex Doc/mac/libframework.tex Doc/mac/libmacic.tex Doc/mac/undoc.tex Doc/mac/using.tex Doc/ref/ref1.tex Doc/ref/ref3.tex Doc/ref/ref5.tex Doc/ref/ref6.tex Doc/ref/ref7.tex Doc/texinputs/python.sty Doc/tut/tut.tex Doc/whatsnew/whatsnew23.tex Doc/whatsnew/whatsnew24.tex Doc/whatsnew/whatsnew25.tex Doc/whatsnew/whatsnew26.tex Include/fileobject.h Include/pydebug.h Include/pystate.h Include/setobject.h LICENSE Lib/Bastion.py Lib/CGIHTTPServer.py Lib/ConfigParser.py Lib/DocXMLRPCServer.py Lib/HTMLParser.py Lib/SimpleXMLRPCServer.py Lib/SocketServer.py Lib/_strptime.py Lib/bisect.py Lib/cmd.py Lib/collections.py Lib/commands.py Lib/copy_reg.py Lib/csv.py Lib/ctypes/__init__.py Lib/ctypes/test/test_functions.py Lib/ctypes/test/test_memfunctions.py Lib/ctypes/test/test_numbers.py Lib/ctypes/test/test_repr.py Lib/decimal.py Lib/difflib.py Lib/distutils/__init__.py Lib/distutils/command/build_ext.py Lib/distutils/msvccompiler.py Lib/doctest.py Lib/email/_parseaddr.py Lib/email/header.py Lib/email/message.py Lib/email/test/test_email.py Lib/email/test/test_email_renamed.py Lib/ftplib.py Lib/genericpath.py Lib/glob.py Lib/heapq.py Lib/httplib.py Lib/idlelib/MultiCall.py Lib/imaplib.py Lib/logging/handlers.py Lib/macpath.py Lib/ntpath.py Lib/os.py Lib/pdb.doc Lib/pdb.py Lib/popen2.py Lib/poplib.py Lib/posixpath.py Lib/pydoc.py Lib/rexec.py Lib/robotparser.py Lib/sched.py Lib/site.py Lib/smtplib.py Lib/socket.py Lib/sre.py Lib/subprocess.py Lib/tarfile.py Lib/telnetlib.py Lib/tempfile.py Lib/test/README Lib/test/crashers/modify_dict_attr.py Lib/test/infinite_reload.py Lib/test/output/test_operations Lib/test/output/test_popen2 Lib/test/output/test_pty Lib/test/output/test_pyexpat Lib/test/output/test_threadedtempfile Lib/test/output/xmltests Lib/test/outstanding_bugs.py Lib/test/pickletester.py Lib/test/regrtest.py Lib/test/ssl_cert.pem Lib/test/ssl_key.pem Lib/test/string_tests.py Lib/test/test___all__.py Lib/test/test_array.py Lib/test/test_atexit.py Lib/test/test_base64.py Lib/test/test_binascii.py Lib/test/test_bool.py Lib/test/test_bsddb3.py Lib/test/test_builtin.py Lib/test/test_cfgparser.py Lib/test/test_cmath.py Lib/test/test_cmd_line.py Lib/test/test_codecencodings_cn.py Lib/test/test_codecencodings_hk.py Lib/test/test_codecencodings_jp.py Lib/test/test_codecencodings_kr.py Lib/test/test_codecencodings_tw.py Lib/test/test_codecmaps_cn.py Lib/test/test_codecmaps_hk.py Lib/test/test_codecmaps_jp.py Lib/test/test_codecmaps_kr.py Lib/test/test_codecmaps_tw.py Lib/test/test_collections.py Lib/test/test_commands.py Lib/test/test_compile.py Lib/test/test_compiler.py Lib/test/test_complex.py Lib/test/test_contextlib.py Lib/test/test_crypt.py Lib/test/test_csv.py Lib/test/test_ctypes.py Lib/test/test_curses.py Lib/test/test_datetime.py Lib/test/test_defaultdict.py Lib/test/test_deque.py Lib/test/test_descr.py Lib/test/test_descrtut.py Lib/test/test_dict.py Lib/test/test_dis.py Lib/test/test_doctest.py Lib/test/test_email.py Lib/test/test_email_codecs.py Lib/test/test_email_renamed.py Lib/test/test_exceptions.py Lib/test/test_fileinput.py Lib/test/test_fileio.py Lib/test/test_ftplib.py Lib/test/test_functools.py Lib/test/test_gc.py Lib/test/test_getopt.py Lib/test/test_gettext.py Lib/test/test_glob.py Lib/test/test_grammar.py Lib/test/test_htmlparser.py Lib/test/test_httplib.py Lib/test/test_import.py Lib/test/test_itertools.py Lib/test/test_keywordonlyarg.py Lib/test/test_locale.py Lib/test/test_logging.py Lib/test/test_long_future.py Lib/test/test_macpath.py Lib/test/test_mailbox.py Lib/test/test_metaclass.py Lib/test/test_minidom.py Lib/test/test_module.py Lib/test/test_multibytecodec.py Lib/test/test_normalization.py Lib/test/test_ntpath.py Lib/test/test_operations.py Lib/test/test_operator.py Lib/test/test_optparse.py Lib/test/test_os.py Lib/test/test_ossaudiodev.py Lib/test/test_peepholer.py Lib/test/test_popen2.py Lib/test/test_poplib.py Lib/test/test_posixpath.py Lib/test/test_pty.py Lib/test/test_pyexpat.py Lib/test/test_re.py Lib/test/test_robotparser.py Lib/test/test_sax.py Lib/test/test_scope.py Lib/test/test_set.py Lib/test/test_slice.py Lib/test/test_smtplib.py Lib/test/test_socket.py Lib/test/test_socket_ssl.py Lib/test/test_socketserver.py Lib/test/test_stringprep.py Lib/test/test_strptime.py Lib/test/test_struct.py Lib/test/test_structmembers.py Lib/test/test_support.py Lib/test/test_syntax.py Lib/test/test_tarfile.py Lib/test/test_telnetlib.py Lib/test/test_tempfile.py Lib/test/test_textwrap.py Lib/test/test_threadedtempfile.py Lib/test/test_threading_local.py Lib/test/test_unicode.py Lib/test/test_unicode_file.py Lib/test/test_unittest.py Lib/test/test_unpack.py Lib/test/test_urllib.py Lib/test/test_urllib2.py Lib/test/test_urllib2net.py Lib/test/test_userdict.py Lib/test/test_warnings.py Lib/test/test_weakref.py Lib/test/test_wsgiref.py Lib/test/test_zipfile.py Lib/test/test_zlib.py Lib/test/testtar.tar Lib/test/warning_tests.py Lib/textwrap.py Lib/timeit.py Lib/unittest.py Lib/urllib.py Lib/urllib2.py Lib/wave.py Lib/webbrowser.py Lib/zipfile.py Misc/ACKS Misc/NEWS Misc/build.sh Misc/developers.txt Misc/python-config.in Modules/_bsddb.c Modules/_collectionsmodule.c Modules/_ctypes/_ctypes.c Modules/_ctypes/callproc.c Modules/_ctypes/cfield.c Modules/_ctypes/libffi/configure Modules/_ctypes/libffi/configure.ac Modules/_ctypes/libffi/fficonfig.h.in Modules/_cursesmodule.c Modules/_localemodule.c Modules/_struct.c Modules/arraymodule.c Modules/binascii.c Modules/bz2module.c Modules/cPickle.c Modules/cStringIO.c Modules/collectionsmodule.c Modules/datetimemodule.c Modules/getpath.c Modules/main.c Modules/operator.c Modules/posixmodule.c Modules/readline.c Modules/socketmodule.c Modules/timemodule.c Objects/complexobject.c Objects/dictobject.c Objects/exceptions.c Objects/fileobject.c Objects/frameobject.c Objects/longobject.c Objects/setobject.c Objects/sliceobject.c Objects/stringobject.c Objects/typeobject.c PC/VC6/pcbuild.dsw PC/_winreg.c PC/config.c PC/getpathp.c PCbuild/pythoncore.vcproj PCbuild8/pythoncore.vcproj Python/ast.c Python/bltinmodule.c Python/ceval.c Python/compile.c Python/dynload_win.c Python/errors.c Python/fmod.c Python/import.c Python/peephole.c Python/pystate.c Python/pythonrun.c Python/sysmodule.c Python/thread_nt.h README Tools/pybench/pybench.py configure.in setup.py Message-ID: <20070427195527.7EECB1E400D@bag.python.org> Author: guido.van.rossum Date: Fri Apr 27 21:54:29 2007 New Revision: 55005 Added: python/branches/p3yk/Doc/ext/shoddy.c - copied unchanged from r54985, python/trunk/Doc/ext/shoddy.c python/branches/p3yk/Lib/collections.py - copied, changed from r54985, python/trunk/Lib/collections.py python/branches/p3yk/Lib/test/infinite_reload.py - copied unchanged from r54985, python/trunk/Lib/test/infinite_reload.py python/branches/p3yk/Lib/test/ssl_cert.pem - copied unchanged from r54985, python/trunk/Lib/test/ssl_cert.pem python/branches/p3yk/Lib/test/ssl_key.pem - copied unchanged from r54985, python/trunk/Lib/test/ssl_key.pem python/branches/p3yk/Lib/test/test_collections.py - copied unchanged from r54985, python/trunk/Lib/test/test_collections.py python/branches/p3yk/Lib/test/test_ftplib.py - copied unchanged from r54985, python/trunk/Lib/test/test_ftplib.py python/branches/p3yk/Lib/test/test_poplib.py - copied unchanged from r54985, python/trunk/Lib/test/test_poplib.py python/branches/p3yk/Lib/test/test_smtplib.py - copied unchanged from r54985, python/trunk/Lib/test/test_smtplib.py python/branches/p3yk/Lib/test/test_telnetlib.py - copied unchanged from r54985, python/trunk/Lib/test/test_telnetlib.py python/branches/p3yk/Lib/test/warning_tests.py - copied unchanged from r54985, python/trunk/Lib/test/warning_tests.py python/branches/p3yk/Modules/_collectionsmodule.c (contents, props changed) Removed: python/branches/p3yk/Lib/test/output/test_operations python/branches/p3yk/Lib/test/output/test_popen2 python/branches/p3yk/Lib/test/output/test_pty python/branches/p3yk/Lib/test/output/test_pyexpat python/branches/p3yk/Lib/test/output/test_threadedtempfile python/branches/p3yk/Lib/test/output/xmltests python/branches/p3yk/Lib/test/test_operations.py python/branches/p3yk/Modules/collectionsmodule.c python/branches/p3yk/Python/fmod.c Modified: python/branches/p3yk/ (props changed) python/branches/p3yk/Demo/parser/unparse.py python/branches/p3yk/Doc/api/abstract.tex python/branches/p3yk/Doc/api/concrete.tex python/branches/p3yk/Doc/api/init.tex python/branches/p3yk/Doc/api/memory.tex python/branches/p3yk/Doc/api/newtypes.tex python/branches/p3yk/Doc/api/utilities.tex python/branches/p3yk/Doc/commontex/copyright.tex python/branches/p3yk/Doc/commontex/license.tex python/branches/p3yk/Doc/dist/dist.tex python/branches/p3yk/Doc/ext/newtypes.tex python/branches/p3yk/Doc/inst/inst.tex python/branches/p3yk/Doc/lib/compiler.tex python/branches/p3yk/Doc/lib/email.tex python/branches/p3yk/Doc/lib/emailutil.tex python/branches/p3yk/Doc/lib/libamoeba.tex python/branches/p3yk/Doc/lib/libasyncore.tex python/branches/p3yk/Doc/lib/libbsddb.tex python/branches/p3yk/Doc/lib/libcfgparser.tex python/branches/p3yk/Doc/lib/libcgitb.tex python/branches/p3yk/Doc/lib/libcmath.tex python/branches/p3yk/Doc/lib/libcmd.tex python/branches/p3yk/Doc/lib/libcode.tex python/branches/p3yk/Doc/lib/libcodecs.tex python/branches/p3yk/Doc/lib/libcollections.tex python/branches/p3yk/Doc/lib/libcommands.tex python/branches/p3yk/Doc/lib/libconsts.tex python/branches/p3yk/Doc/lib/libcookielib.tex python/branches/p3yk/Doc/lib/libctypes.tex python/branches/p3yk/Doc/lib/libcurses.tex python/branches/p3yk/Doc/lib/libcursespanel.tex python/branches/p3yk/Doc/lib/libdatetime.tex python/branches/p3yk/Doc/lib/libdbhash.tex python/branches/p3yk/Doc/lib/libdecimal.tex python/branches/p3yk/Doc/lib/libdl.tex python/branches/p3yk/Doc/lib/libdoctest.tex python/branches/p3yk/Doc/lib/libdocxmlrpc.tex python/branches/p3yk/Doc/lib/libdumbdbm.tex python/branches/p3yk/Doc/lib/libetree.tex python/branches/p3yk/Doc/lib/libfm.tex python/branches/p3yk/Doc/lib/libfnmatch.tex python/branches/p3yk/Doc/lib/libftplib.tex python/branches/p3yk/Doc/lib/libfuncs.tex python/branches/p3yk/Doc/lib/libgettext.tex python/branches/p3yk/Doc/lib/libhmac.tex python/branches/p3yk/Doc/lib/libhotshot.tex python/branches/p3yk/Doc/lib/libhtmllib.tex python/branches/p3yk/Doc/lib/libhtmlparser.tex python/branches/p3yk/Doc/lib/libhttplib.tex python/branches/p3yk/Doc/lib/libimaplib.tex python/branches/p3yk/Doc/lib/liblogging.tex python/branches/p3yk/Doc/lib/libmailbox.tex python/branches/p3yk/Doc/lib/libmimetools.tex python/branches/p3yk/Doc/lib/libmimetypes.tex python/branches/p3yk/Doc/lib/libmimewriter.tex python/branches/p3yk/Doc/lib/libmmap.tex python/branches/p3yk/Doc/lib/libmsilib.tex python/branches/p3yk/Doc/lib/libmultifile.tex python/branches/p3yk/Doc/lib/libmutex.tex python/branches/p3yk/Doc/lib/libnetrc.tex python/branches/p3yk/Doc/lib/libnntplib.tex python/branches/p3yk/Doc/lib/liboptparse.tex python/branches/p3yk/Doc/lib/libos.tex python/branches/p3yk/Doc/lib/libpdb.tex python/branches/p3yk/Doc/lib/libpipes.tex python/branches/p3yk/Doc/lib/libplatform.tex python/branches/p3yk/Doc/lib/libpopen2.tex python/branches/p3yk/Doc/lib/libpoplib.tex python/branches/p3yk/Doc/lib/libposixfile.tex python/branches/p3yk/Doc/lib/libposixpath.tex python/branches/p3yk/Doc/lib/libpprint.tex python/branches/p3yk/Doc/lib/libqueue.tex python/branches/p3yk/Doc/lib/libre.tex python/branches/p3yk/Doc/lib/librepr.tex python/branches/p3yk/Doc/lib/librexec.tex python/branches/p3yk/Doc/lib/librfc822.tex python/branches/p3yk/Doc/lib/libsched.tex python/branches/p3yk/Doc/lib/libselect.tex python/branches/p3yk/Doc/lib/libshlex.tex python/branches/p3yk/Doc/lib/libshutil.tex python/branches/p3yk/Doc/lib/libsimplexmlrpc.tex python/branches/p3yk/Doc/lib/libsite.tex python/branches/p3yk/Doc/lib/libsmtplib.tex python/branches/p3yk/Doc/lib/libsocket.tex python/branches/p3yk/Doc/lib/libsqlite3.tex python/branches/p3yk/Doc/lib/libstdtypes.tex python/branches/p3yk/Doc/lib/libstring.tex python/branches/p3yk/Doc/lib/libsubprocess.tex python/branches/p3yk/Doc/lib/libsun.tex python/branches/p3yk/Doc/lib/libsys.tex python/branches/p3yk/Doc/lib/libtarfile.tex python/branches/p3yk/Doc/lib/libtelnetlib.tex python/branches/p3yk/Doc/lib/libtempfile.tex python/branches/p3yk/Doc/lib/libtest.tex python/branches/p3yk/Doc/lib/libtextwrap.tex python/branches/p3yk/Doc/lib/libthreading.tex python/branches/p3yk/Doc/lib/libtimeit.tex python/branches/p3yk/Doc/lib/libturtle.tex python/branches/p3yk/Doc/lib/libunittest.tex python/branches/p3yk/Doc/lib/liburllib2.tex python/branches/p3yk/Doc/lib/liburlparse.tex python/branches/p3yk/Doc/lib/libwebbrowser.tex python/branches/p3yk/Doc/lib/libwinreg.tex python/branches/p3yk/Doc/lib/libxmlrpclib.tex python/branches/p3yk/Doc/lib/libzipfile.tex python/branches/p3yk/Doc/lib/libzlib.tex python/branches/p3yk/Doc/mac/libframework.tex python/branches/p3yk/Doc/mac/libmacic.tex python/branches/p3yk/Doc/mac/undoc.tex python/branches/p3yk/Doc/mac/using.tex python/branches/p3yk/Doc/ref/ref1.tex python/branches/p3yk/Doc/ref/ref3.tex python/branches/p3yk/Doc/ref/ref5.tex python/branches/p3yk/Doc/ref/ref6.tex python/branches/p3yk/Doc/ref/ref7.tex python/branches/p3yk/Doc/texinputs/python.sty python/branches/p3yk/Doc/tut/tut.tex python/branches/p3yk/Doc/whatsnew/whatsnew23.tex python/branches/p3yk/Doc/whatsnew/whatsnew24.tex python/branches/p3yk/Doc/whatsnew/whatsnew25.tex python/branches/p3yk/Doc/whatsnew/whatsnew26.tex python/branches/p3yk/Include/fileobject.h python/branches/p3yk/Include/pydebug.h python/branches/p3yk/Include/pystate.h python/branches/p3yk/Include/setobject.h python/branches/p3yk/LICENSE python/branches/p3yk/Lib/Bastion.py python/branches/p3yk/Lib/CGIHTTPServer.py python/branches/p3yk/Lib/ConfigParser.py python/branches/p3yk/Lib/DocXMLRPCServer.py python/branches/p3yk/Lib/HTMLParser.py python/branches/p3yk/Lib/SimpleXMLRPCServer.py python/branches/p3yk/Lib/SocketServer.py python/branches/p3yk/Lib/_strptime.py python/branches/p3yk/Lib/bisect.py python/branches/p3yk/Lib/cmd.py python/branches/p3yk/Lib/commands.py python/branches/p3yk/Lib/copy_reg.py python/branches/p3yk/Lib/csv.py python/branches/p3yk/Lib/ctypes/__init__.py python/branches/p3yk/Lib/ctypes/test/test_functions.py python/branches/p3yk/Lib/ctypes/test/test_memfunctions.py python/branches/p3yk/Lib/ctypes/test/test_numbers.py python/branches/p3yk/Lib/ctypes/test/test_repr.py python/branches/p3yk/Lib/decimal.py python/branches/p3yk/Lib/difflib.py python/branches/p3yk/Lib/distutils/__init__.py python/branches/p3yk/Lib/distutils/command/build_ext.py python/branches/p3yk/Lib/distutils/msvccompiler.py python/branches/p3yk/Lib/doctest.py python/branches/p3yk/Lib/email/_parseaddr.py python/branches/p3yk/Lib/email/header.py python/branches/p3yk/Lib/email/message.py python/branches/p3yk/Lib/email/test/test_email.py python/branches/p3yk/Lib/email/test/test_email_renamed.py python/branches/p3yk/Lib/ftplib.py python/branches/p3yk/Lib/genericpath.py python/branches/p3yk/Lib/glob.py python/branches/p3yk/Lib/heapq.py python/branches/p3yk/Lib/httplib.py python/branches/p3yk/Lib/idlelib/MultiCall.py python/branches/p3yk/Lib/imaplib.py python/branches/p3yk/Lib/logging/handlers.py python/branches/p3yk/Lib/macpath.py python/branches/p3yk/Lib/ntpath.py python/branches/p3yk/Lib/os.py python/branches/p3yk/Lib/pdb.doc python/branches/p3yk/Lib/pdb.py python/branches/p3yk/Lib/popen2.py python/branches/p3yk/Lib/poplib.py python/branches/p3yk/Lib/posixpath.py python/branches/p3yk/Lib/pydoc.py python/branches/p3yk/Lib/rexec.py python/branches/p3yk/Lib/robotparser.py python/branches/p3yk/Lib/sched.py python/branches/p3yk/Lib/site.py python/branches/p3yk/Lib/smtplib.py python/branches/p3yk/Lib/socket.py python/branches/p3yk/Lib/sre.py python/branches/p3yk/Lib/subprocess.py python/branches/p3yk/Lib/tarfile.py python/branches/p3yk/Lib/telnetlib.py python/branches/p3yk/Lib/tempfile.py python/branches/p3yk/Lib/test/README python/branches/p3yk/Lib/test/crashers/modify_dict_attr.py python/branches/p3yk/Lib/test/outstanding_bugs.py python/branches/p3yk/Lib/test/pickletester.py python/branches/p3yk/Lib/test/regrtest.py python/branches/p3yk/Lib/test/string_tests.py python/branches/p3yk/Lib/test/test___all__.py python/branches/p3yk/Lib/test/test_array.py python/branches/p3yk/Lib/test/test_atexit.py python/branches/p3yk/Lib/test/test_base64.py python/branches/p3yk/Lib/test/test_binascii.py python/branches/p3yk/Lib/test/test_bool.py python/branches/p3yk/Lib/test/test_bsddb3.py python/branches/p3yk/Lib/test/test_builtin.py python/branches/p3yk/Lib/test/test_cfgparser.py python/branches/p3yk/Lib/test/test_cmath.py python/branches/p3yk/Lib/test/test_cmd_line.py python/branches/p3yk/Lib/test/test_codecencodings_cn.py python/branches/p3yk/Lib/test/test_codecencodings_hk.py python/branches/p3yk/Lib/test/test_codecencodings_jp.py python/branches/p3yk/Lib/test/test_codecencodings_kr.py python/branches/p3yk/Lib/test/test_codecencodings_tw.py python/branches/p3yk/Lib/test/test_codecmaps_cn.py python/branches/p3yk/Lib/test/test_codecmaps_hk.py python/branches/p3yk/Lib/test/test_codecmaps_jp.py python/branches/p3yk/Lib/test/test_codecmaps_kr.py python/branches/p3yk/Lib/test/test_codecmaps_tw.py python/branches/p3yk/Lib/test/test_commands.py python/branches/p3yk/Lib/test/test_compile.py python/branches/p3yk/Lib/test/test_compiler.py python/branches/p3yk/Lib/test/test_complex.py python/branches/p3yk/Lib/test/test_contextlib.py python/branches/p3yk/Lib/test/test_crypt.py python/branches/p3yk/Lib/test/test_csv.py python/branches/p3yk/Lib/test/test_ctypes.py python/branches/p3yk/Lib/test/test_curses.py python/branches/p3yk/Lib/test/test_datetime.py python/branches/p3yk/Lib/test/test_defaultdict.py python/branches/p3yk/Lib/test/test_deque.py python/branches/p3yk/Lib/test/test_descr.py python/branches/p3yk/Lib/test/test_descrtut.py python/branches/p3yk/Lib/test/test_dict.py python/branches/p3yk/Lib/test/test_dis.py python/branches/p3yk/Lib/test/test_doctest.py python/branches/p3yk/Lib/test/test_email.py python/branches/p3yk/Lib/test/test_email_codecs.py python/branches/p3yk/Lib/test/test_email_renamed.py python/branches/p3yk/Lib/test/test_exceptions.py python/branches/p3yk/Lib/test/test_fileinput.py python/branches/p3yk/Lib/test/test_fileio.py python/branches/p3yk/Lib/test/test_functools.py python/branches/p3yk/Lib/test/test_gc.py python/branches/p3yk/Lib/test/test_getopt.py python/branches/p3yk/Lib/test/test_gettext.py python/branches/p3yk/Lib/test/test_glob.py python/branches/p3yk/Lib/test/test_grammar.py python/branches/p3yk/Lib/test/test_htmlparser.py python/branches/p3yk/Lib/test/test_httplib.py python/branches/p3yk/Lib/test/test_import.py python/branches/p3yk/Lib/test/test_itertools.py python/branches/p3yk/Lib/test/test_keywordonlyarg.py python/branches/p3yk/Lib/test/test_locale.py python/branches/p3yk/Lib/test/test_logging.py python/branches/p3yk/Lib/test/test_long_future.py python/branches/p3yk/Lib/test/test_macpath.py python/branches/p3yk/Lib/test/test_mailbox.py python/branches/p3yk/Lib/test/test_metaclass.py python/branches/p3yk/Lib/test/test_minidom.py python/branches/p3yk/Lib/test/test_module.py python/branches/p3yk/Lib/test/test_multibytecodec.py python/branches/p3yk/Lib/test/test_normalization.py python/branches/p3yk/Lib/test/test_ntpath.py python/branches/p3yk/Lib/test/test_operator.py python/branches/p3yk/Lib/test/test_optparse.py python/branches/p3yk/Lib/test/test_os.py python/branches/p3yk/Lib/test/test_ossaudiodev.py python/branches/p3yk/Lib/test/test_peepholer.py python/branches/p3yk/Lib/test/test_popen2.py python/branches/p3yk/Lib/test/test_posixpath.py python/branches/p3yk/Lib/test/test_pty.py python/branches/p3yk/Lib/test/test_pyexpat.py python/branches/p3yk/Lib/test/test_re.py python/branches/p3yk/Lib/test/test_robotparser.py python/branches/p3yk/Lib/test/test_sax.py python/branches/p3yk/Lib/test/test_scope.py python/branches/p3yk/Lib/test/test_set.py python/branches/p3yk/Lib/test/test_slice.py python/branches/p3yk/Lib/test/test_socket.py python/branches/p3yk/Lib/test/test_socket_ssl.py python/branches/p3yk/Lib/test/test_socketserver.py python/branches/p3yk/Lib/test/test_stringprep.py python/branches/p3yk/Lib/test/test_strptime.py python/branches/p3yk/Lib/test/test_struct.py python/branches/p3yk/Lib/test/test_structmembers.py python/branches/p3yk/Lib/test/test_support.py python/branches/p3yk/Lib/test/test_syntax.py python/branches/p3yk/Lib/test/test_tarfile.py python/branches/p3yk/Lib/test/test_tempfile.py python/branches/p3yk/Lib/test/test_textwrap.py python/branches/p3yk/Lib/test/test_threadedtempfile.py python/branches/p3yk/Lib/test/test_threading_local.py python/branches/p3yk/Lib/test/test_unicode.py python/branches/p3yk/Lib/test/test_unicode_file.py python/branches/p3yk/Lib/test/test_unittest.py python/branches/p3yk/Lib/test/test_unpack.py python/branches/p3yk/Lib/test/test_urllib.py python/branches/p3yk/Lib/test/test_urllib2.py python/branches/p3yk/Lib/test/test_urllib2net.py python/branches/p3yk/Lib/test/test_userdict.py python/branches/p3yk/Lib/test/test_warnings.py python/branches/p3yk/Lib/test/test_weakref.py python/branches/p3yk/Lib/test/test_wsgiref.py python/branches/p3yk/Lib/test/test_zipfile.py python/branches/p3yk/Lib/test/test_zlib.py python/branches/p3yk/Lib/test/testtar.tar python/branches/p3yk/Lib/textwrap.py python/branches/p3yk/Lib/timeit.py python/branches/p3yk/Lib/unittest.py python/branches/p3yk/Lib/urllib.py python/branches/p3yk/Lib/urllib2.py python/branches/p3yk/Lib/wave.py python/branches/p3yk/Lib/webbrowser.py python/branches/p3yk/Lib/zipfile.py python/branches/p3yk/Misc/ACKS python/branches/p3yk/Misc/NEWS python/branches/p3yk/Misc/build.sh python/branches/p3yk/Misc/developers.txt python/branches/p3yk/Misc/python-config.in python/branches/p3yk/Modules/_bsddb.c python/branches/p3yk/Modules/_ctypes/_ctypes.c python/branches/p3yk/Modules/_ctypes/callproc.c python/branches/p3yk/Modules/_ctypes/cfield.c python/branches/p3yk/Modules/_ctypes/libffi/configure python/branches/p3yk/Modules/_ctypes/libffi/configure.ac python/branches/p3yk/Modules/_ctypes/libffi/fficonfig.h.in python/branches/p3yk/Modules/_cursesmodule.c python/branches/p3yk/Modules/_localemodule.c python/branches/p3yk/Modules/_struct.c python/branches/p3yk/Modules/arraymodule.c python/branches/p3yk/Modules/binascii.c python/branches/p3yk/Modules/bz2module.c python/branches/p3yk/Modules/cPickle.c python/branches/p3yk/Modules/cStringIO.c python/branches/p3yk/Modules/datetimemodule.c python/branches/p3yk/Modules/getpath.c python/branches/p3yk/Modules/main.c python/branches/p3yk/Modules/operator.c python/branches/p3yk/Modules/posixmodule.c python/branches/p3yk/Modules/readline.c python/branches/p3yk/Modules/socketmodule.c python/branches/p3yk/Modules/timemodule.c python/branches/p3yk/Objects/complexobject.c python/branches/p3yk/Objects/dictobject.c python/branches/p3yk/Objects/exceptions.c python/branches/p3yk/Objects/fileobject.c python/branches/p3yk/Objects/frameobject.c python/branches/p3yk/Objects/longobject.c python/branches/p3yk/Objects/setobject.c python/branches/p3yk/Objects/sliceobject.c python/branches/p3yk/Objects/stringobject.c python/branches/p3yk/Objects/typeobject.c python/branches/p3yk/PC/VC6/pcbuild.dsw python/branches/p3yk/PC/_winreg.c python/branches/p3yk/PC/config.c python/branches/p3yk/PC/getpathp.c python/branches/p3yk/PCbuild/pythoncore.vcproj python/branches/p3yk/PCbuild8/pythoncore.vcproj 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/dynload_win.c python/branches/p3yk/Python/errors.c python/branches/p3yk/Python/import.c python/branches/p3yk/Python/peephole.c python/branches/p3yk/Python/pystate.c python/branches/p3yk/Python/pythonrun.c python/branches/p3yk/Python/sysmodule.c python/branches/p3yk/Python/thread_nt.h python/branches/p3yk/README python/branches/p3yk/Tools/pybench/pybench.py python/branches/p3yk/configure.in python/branches/p3yk/setup.py Log: Merged revisions 53952-54987 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r53954 | jeremy.hylton | 2007-02-26 10:41:18 -0800 (Mon, 26 Feb 2007) | 10 lines Do not copy free variables to locals in class namespaces. Fixes bug 1569356, but at the cost of a minor incompatibility in locals(). Add test that verifies that the class namespace is not polluted. Also clarify the behavior in the library docs. Along the way, cleaned up the dict_to_map and map_to_dict implementations and added some comments that explain what they do. ........ r53955 | jeremy.hylton | 2007-02-26 11:00:20 -0800 (Mon, 26 Feb 2007) | 2 lines Fix assertion. ........ r53969 | neal.norwitz | 2007-02-26 14:41:45 -0800 (Mon, 26 Feb 2007) | 3 lines When printing an unraisable error, don't print exceptions. before the name. This duplicates the behavior whening normally printing exceptions. ........ r53970 | andrew.kuchling | 2007-02-26 15:02:47 -0800 (Mon, 26 Feb 2007) | 1 line Markup fix ........ r53975 | neal.norwitz | 2007-02-26 15:48:27 -0800 (Mon, 26 Feb 2007) | 3 lines SF #1669182, 2.5 was already fixed. Just assert in 2.6 since string exceptions are gone. ........ r53976 | andrew.kuchling | 2007-02-26 15:54:17 -0800 (Mon, 26 Feb 2007) | 1 line Add some items ........ r53981 | jeremy.hylton | 2007-02-26 17:01:59 -0800 (Mon, 26 Feb 2007) | 4 lines Fix long-standing bug in name mangling for package imports Reported by Mike Verdone. ........ r53993 | jeremy.hylton | 2007-02-27 08:00:06 -0800 (Tue, 27 Feb 2007) | 2 lines tabify ........ r53994 | jeremy.hylton | 2007-02-27 08:13:23 -0800 (Tue, 27 Feb 2007) | 5 lines tabify Note that ast.c still has a mix of tabs and spaces, because it attempts to use four-space indents for more of the new code. ........ r53996 | jeremy.hylton | 2007-02-27 09:24:48 -0800 (Tue, 27 Feb 2007) | 2 lines whitespace normalization ........ r53997 | jeremy.hylton | 2007-02-27 10:29:45 -0800 (Tue, 27 Feb 2007) | 24 lines Add checking for a number of metaclass error conditions. We add some new rules that are required for preserving internal invariants of types. 1. If type (or a subclass of type) appears in bases, it must appear before any non-type bases. If a non-type base (like a regular new-style class) occurred first, it could trick type into allocating the new class an __dict__ which must be impossible. 2. There are several checks that are made of bases when creating a type. Those checks are now repeated when assigning to __bases__. We also add the restriction that assignment to __bases__ may not change the metaclass of the type. Add new tests for these cases and for a few other oddball errors that were no previously tested. Remove a crasher test that was fixed. Also some internal refactoring: Extract the code to find the most derived metaclass of a type and its bases. It is now needed in two places. Rewrite the TypeError checks in test_descr to use doctest. The tests now clearly show what exception they expect to see. ........ r53998 | jeremy.hylton | 2007-02-27 10:33:31 -0800 (Tue, 27 Feb 2007) | 2 lines Add news about changes to metaclasses and __bases__ error checking. ........ r54016 | armin.rigo | 2007-02-28 01:25:29 -0800 (Wed, 28 Feb 2007) | 3 lines Modify the segfaulting example to show why r53997 is not a solution to it. ........ r54022 | brett.cannon | 2007-02-28 10:15:00 -0800 (Wed, 28 Feb 2007) | 2 lines Add a test for instantiating SyntaxError with no arguments. ........ r54026 | raymond.hettinger | 2007-02-28 10:27:41 -0800 (Wed, 28 Feb 2007) | 1 line Docstring nit. ........ r54033 | raymond.hettinger | 2007-02-28 10:37:52 -0800 (Wed, 28 Feb 2007) | 1 line Prepare collections module for pure python code entries. ........ r54053 | raymond.hettinger | 2007-02-28 22:16:43 -0800 (Wed, 28 Feb 2007) | 1 line Add collections.NamedTuple ........ r54054 | neal.norwitz | 2007-02-28 23:04:41 -0800 (Wed, 28 Feb 2007) | 1 line Add Pat and Eric for work on PEP 3101 in the sandbox ........ r54061 | andrew.kuchling | 2007-03-01 06:36:12 -0800 (Thu, 01 Mar 2007) | 1 line Add NamedTuple ........ r54080 | georg.brandl | 2007-03-02 06:37:12 -0800 (Fri, 02 Mar 2007) | 2 lines Bug #1628895: some better tries to find HTML documentation in pydoc. ........ r54086 | raymond.hettinger | 2007-03-02 11:20:46 -0800 (Fri, 02 Mar 2007) | 1 line Fix embarrassing typo and fix constantification of None ........ r54088 | georg.brandl | 2007-03-02 12:30:14 -0800 (Fri, 02 Mar 2007) | 2 lines Bugs #1668032, #1668036, #1669304: clarify behavior of PyMem_Realloc and _Resize. ........ r54114 | georg.brandl | 2007-03-04 09:18:54 -0800 (Sun, 04 Mar 2007) | 2 lines Fix a bug in test_dict and test_userdict, found at the PyPy sprint. ........ r54124 | skip.montanaro | 2007-03-04 12:52:28 -0800 (Sun, 04 Mar 2007) | 2 lines Teach setup.py how to find Berkeley DB on Macs using MacPorts. ........ r54125 | skip.montanaro | 2007-03-04 12:54:12 -0800 (Sun, 04 Mar 2007) | 1 line note MacPorts/BerkDB change in setup.py ........ r54136 | neal.norwitz | 2007-03-04 23:52:01 -0800 (Sun, 04 Mar 2007) | 1 line Added Pete for 3101 too ........ r54138 | facundo.batista | 2007-03-05 08:31:54 -0800 (Mon, 05 Mar 2007) | 1 line Minor corrections to docs, and an explanation comentary ........ r54139 | georg.brandl | 2007-03-05 14:28:08 -0800 (Mon, 05 Mar 2007) | 3 lines Patch #1674228: when assigning a slice (old-style), check for the sq_ass_slice instead of the sq_slice slot. ........ r54149 | georg.brandl | 2007-03-06 01:33:01 -0800 (Tue, 06 Mar 2007) | 3 lines Nit: a struct field is set to GenericAlloc, not GenericAlloc(). ........ r54150 | georg.brandl | 2007-03-06 02:02:47 -0800 (Tue, 06 Mar 2007) | 3 lines Patch #1671450: add a section about subclassing builtin types to the "extending and embedding" tutorial. ........ r54152 | martin.v.loewis | 2007-03-06 02:41:24 -0800 (Tue, 06 Mar 2007) | 2 lines Patch #1121142: Implement ZipFile.open. ........ r54154 | georg.brandl | 2007-03-06 03:51:14 -0800 (Tue, 06 Mar 2007) | 2 lines A test case for the fix in #1674228. ........ r54156 | georg.brandl | 2007-03-06 03:52:24 -0800 (Tue, 06 Mar 2007) | 2 lines Patch #1672481: fix bug in idlelib.MultiCall. ........ r54159 | georg.brandl | 2007-03-06 04:17:50 -0800 (Tue, 06 Mar 2007) | 1 line Bug #1674503: close the file opened by execfile() in an error condition. ........ r54160 | georg.brandl | 2007-03-06 05:32:52 -0800 (Tue, 06 Mar 2007) | 3 lines Fix another reincarnation of bug #1576657 in defaultdict. ........ r54162 | georg.brandl | 2007-03-06 05:35:00 -0800 (Tue, 06 Mar 2007) | 2 lines A test case for the defaultdict KeyError bug. ........ r54164 | georg.brandl | 2007-03-06 05:37:45 -0800 (Tue, 06 Mar 2007) | 3 lines Patch #1663234: you can now run doctest on test files and modules using "python -m doctest [-v] filename ...". ........ r54165 | martin.v.loewis | 2007-03-06 06:43:00 -0800 (Tue, 06 Mar 2007) | 3 lines Patch #912410: Replace HTML entity references for attribute values in HTMLParser. ........ r54166 | skip.montanaro | 2007-03-06 07:41:38 -0800 (Tue, 06 Mar 2007) | 1 line patch 1673619 - identify extension modules which cannot be built ........ r54167 | guido.van.rossum | 2007-03-06 07:50:01 -0800 (Tue, 06 Mar 2007) | 5 lines Patch #1646728: datetime.fromtimestamp fails with negative fractional times. With unittest. Somebody please backport to 2.5. ........ r54169 | georg.brandl | 2007-03-06 09:49:14 -0800 (Tue, 06 Mar 2007) | 2 lines Fix cmp vs. key argument for list.sort. ........ r54170 | georg.brandl | 2007-03-06 10:21:32 -0800 (Tue, 06 Mar 2007) | 2 lines Small nit, found by Neal. ........ r54171 | georg.brandl | 2007-03-06 10:29:58 -0800 (Tue, 06 Mar 2007) | 3 lines Patch #1602128: clarify that richcmp methods can return NotImplemented and should return True or False otherwise. ........ r54173 | georg.brandl | 2007-03-06 10:41:12 -0800 (Tue, 06 Mar 2007) | 2 lines Patch #1638879: don't accept strings with embedded NUL bytes in long(). ........ r54175 | georg.brandl | 2007-03-06 10:47:31 -0800 (Tue, 06 Mar 2007) | 2 lines Patch #1673121: update README wrt. OSX default shell. ........ r54177 | georg.brandl | 2007-03-06 10:59:11 -0800 (Tue, 06 Mar 2007) | 3 lines Patch #1654417: make operator.{get,set,del}slice use the full range of Py_ssize_t. ........ r54180 | walter.doerwald | 2007-03-06 12:38:57 -0800 (Tue, 06 Mar 2007) | 4 lines Patch for bug #1633621: if curses.resizeterm() or curses.resize_term() is called, update _curses.LINES, _curses.COLS, curses.LINES and curses.COLS. ........ r54182 | walter.doerwald | 2007-03-06 13:15:24 -0800 (Tue, 06 Mar 2007) | 2 lines Document change to curses. ........ r54188 | georg.brandl | 2007-03-06 16:34:46 -0800 (Tue, 06 Mar 2007) | 5 lines Variant of patch #697613: don't exit the interpreter on a SystemExit exception if the -i command line option or PYTHONINSPECT environment variable is given, but break into the interactive interpreter just like on other exceptions or normal program exit. (backport) ........ r54189 | georg.brandl | 2007-03-06 16:40:28 -0800 (Tue, 06 Mar 2007) | 4 lines Patch #703779: unset __file__ in __main__ after running a file. This makes the filenames the warning module prints much more sensible when a PYTHONSTARTUP file is used. ........ r54192 | george.yoshida | 2007-03-06 20:21:18 -0800 (Tue, 06 Mar 2007) | 2 lines add versionadded info ........ r54195 | georg.brandl | 2007-03-06 23:39:06 -0800 (Tue, 06 Mar 2007) | 2 lines Patch #812285: allow multiple auth schemes in AbstractBasicAuthHandler. ........ r54197 | georg.brandl | 2007-03-07 00:31:51 -0800 (Wed, 07 Mar 2007) | 3 lines Patch #1001604: glob.glob() now returns unicode filenames if it was given a unicode argument and os.listdir() returns unicode filenames. ........ r54199 | georg.brandl | 2007-03-07 01:09:40 -0800 (Wed, 07 Mar 2007) | 3 lines Patches #1550273, #1550272: fix a few bugs in unittest and add a comprehensive test suite for the module. ........ r54201 | georg.brandl | 2007-03-07 01:21:06 -0800 (Wed, 07 Mar 2007) | 3 lines Patch #787789: allow to pass custom TestRunner instances to unittest's main() function. ........ r54202 | georg.brandl | 2007-03-07 01:34:45 -0800 (Wed, 07 Mar 2007) | 2 lines Patch #1669331: clarify shutil.copyfileobj() behavior wrt. file position. ........ r54204 | martin.v.loewis | 2007-03-07 03:04:33 -0800 (Wed, 07 Mar 2007) | 2 lines Bug #1115886: os.path.splitext('.cshrc') gives now ('.cshrc', ''). ........ r54206 | georg.brandl | 2007-03-07 03:37:42 -0800 (Wed, 07 Mar 2007) | 2 lines Patch #1675471: convert test_pty to unittest. ........ r54207 | georg.brandl | 2007-03-07 03:54:49 -0800 (Wed, 07 Mar 2007) | 4 lines Add some sanity checks to unittest.TestSuite's addTest(s) methods. Fixes #878275. ........ r54209 | guido.van.rossum | 2007-03-07 07:16:29 -0800 (Wed, 07 Mar 2007) | 3 lines Windows doesn't support negative timestamps. Skip the tests involving them if os.name == "nt". ........ r54219 | martin.v.loewis | 2007-03-08 05:42:43 -0800 (Thu, 08 Mar 2007) | 2 lines Add missing ) in parenthical remark. ........ r54220 | georg.brandl | 2007-03-08 09:49:06 -0800 (Thu, 08 Mar 2007) | 2 lines Fix #1676656: \em is different from \emph... ........ r54222 | georg.brandl | 2007-03-08 10:37:31 -0800 (Thu, 08 Mar 2007) | 2 lines Add a NEWS entry for rev. 54207,8. ........ r54225 | raymond.hettinger | 2007-03-08 11:24:27 -0800 (Thu, 08 Mar 2007) | 1 line SF 1676321: empty() returned wrong result ........ r54227 | collin.winter | 2007-03-08 11:58:14 -0800 (Thu, 08 Mar 2007) | 1 line Backported r54226 from p3yk: Move test_unittest, test_doctest and test_doctest2 higher up in the testing order. ........ r54230 | raymond.hettinger | 2007-03-08 13:33:47 -0800 (Thu, 08 Mar 2007) | 1 line SF #1637850: make_table in difflib did not work with unicode ........ r54232 | collin.winter | 2007-03-08 14:16:25 -0800 (Thu, 08 Mar 2007) | 1 line Patch #1668482: don't use '-' in mkstemp ........ r54233 | brett.cannon | 2007-03-08 15:58:11 -0800 (Thu, 08 Mar 2007) | 10 lines Introduce test.test_support.TransientResource. It's a context manager to surround calls to resources that may or may not be available. Specifying the expected exception and attributes to be raised if the resource is not available prevents overly broad catching of exceptions. This is meant to help suppress spurious failures by raising test.test_support.ResourceDenied if the exception matches. It would probably be good to go through the various network tests and surround the calls to catch connection timeouts (as done with test_socket_ssl in this commit). ........ r54234 | collin.winter | 2007-03-08 19:15:56 -0800 (Thu, 08 Mar 2007) | 1 line Patch #1481079: Support of HTTP_REFERER in CGIHTTPServer.py ........ r54235 | collin.winter | 2007-03-08 19:26:32 -0800 (Thu, 08 Mar 2007) | 1 line Add NEWS item for patch #1481079 (r54234). ........ r54237 | neal.norwitz | 2007-03-08 21:59:01 -0800 (Thu, 08 Mar 2007) | 1 line Fix SF #1676971, Complex OverflowError has a typo ........ r54239 | georg.brandl | 2007-03-09 04:58:41 -0800 (Fri, 09 Mar 2007) | 2 lines Typo. ........ r54240 | martin.v.loewis | 2007-03-09 07:35:55 -0800 (Fri, 09 Mar 2007) | 2 lines Patch #957003: Implement smtplib.LMTP. ........ r54243 | collin.winter | 2007-03-09 10:09:10 -0800 (Fri, 09 Mar 2007) | 2 lines Bug #1629566: clarify the docs on the return values of parsedate() and parsedate_tz() in email.utils and rfc822. ........ r54244 | thomas.heller | 2007-03-09 11:21:28 -0800 (Fri, 09 Mar 2007) | 3 lines Fix bug #1646630: ctypes.string_at(buf, 0) and ctypes.wstring_at(buf, 0) returned string up to the first NUL character. ........ r54245 | martin.v.loewis | 2007-03-09 11:36:01 -0800 (Fri, 09 Mar 2007) | 2 lines Add Ziga Seilnacht. ........ r54247 | collin.winter | 2007-03-09 12:33:07 -0800 (Fri, 09 Mar 2007) | 2 lines Patch #1491866: change the complex() constructor to allow parthensized forms. This means complex(repr(x)) now works instead of raising a ValueError. ........ r54248 | thomas.heller | 2007-03-09 12:39:22 -0800 (Fri, 09 Mar 2007) | 7 lines Bug #1651235: When a tuple was passed to a ctypes function call, Python would crash instead of raising an error. The crash was caused by a section of code that should have been removed long ago, at that time ctypes had other ways to pass parameters to function calls. ........ r54250 | collin.winter | 2007-03-09 15:30:39 -0800 (Fri, 09 Mar 2007) | 1 line Hashing simplification pointed out by Thomas Wouters. ........ r54252 | collin.winter | 2007-03-09 18:23:40 -0800 (Fri, 09 Mar 2007) | 5 lines * Unlink test files before and after each test; hopefully this will cut down on recent buildbot failures in test_islink. * Drop safe_remove() in favor of test_support.unlink(). * Fix the indentation of test_samefile so that it runs. ........ r54253 | collin.winter | 2007-03-09 18:51:26 -0800 (Fri, 09 Mar 2007) | 3 lines Bug #1531963: Make SocketServer.TCPServer's server_address always be equal to calling getsockname() on the server's socket. Will backport. ........ r54254 | neal.norwitz | 2007-03-09 19:19:18 -0800 (Fri, 09 Mar 2007) | 4 lines Simplify a little by handling the TCP case first. Update to use predominant style of spaces around = in args list and print to stderr if debugging. ........ r54256 | collin.winter | 2007-03-09 19:35:34 -0800 (Fri, 09 Mar 2007) | 1 line Add proper attribution for a bug fix. ........ r54257 | georg.brandl | 2007-03-09 23:38:14 -0800 (Fri, 09 Mar 2007) | 2 lines Typos. ........ r54260 | collin.winter | 2007-03-10 06:33:32 -0800 (Sat, 10 Mar 2007) | 1 line Convert an assert to a raise so it works even in the presence of -O. ........ r54262 | collin.winter | 2007-03-10 06:41:48 -0800 (Sat, 10 Mar 2007) | 2 lines Patch #1599845: Add an option to disable the implicit calls to server_bind() and server_activate() in the constructors for TCPServer, SimpleXMLRPCServer and DocXMLRPCServer. ........ r54268 | georg.brandl | 2007-03-11 00:28:46 -0800 (Sun, 11 Mar 2007) | 2 lines Add missing "return" statements in exception handler. ........ r54270 | ziga.seilnacht | 2007-03-11 08:54:54 -0700 (Sun, 11 Mar 2007) | 3 lines Patch #1675981: remove unreachable code from type.__new__() method. __dict__ and __weakref__ are removed from the slots tuple earlier in the code, in the loop that mangles slot names. Will backport. ........ r54271 | collin.winter | 2007-03-11 09:00:20 -0700 (Sun, 11 Mar 2007) | 3 lines Patch #1192590: Fix pdb's "ignore" and "condition" commands so they trap the IndexError caused by passing in an invalid breakpoint number. Will backport. ........ r54274 | vinay.sajip | 2007-03-11 11:32:07 -0700 (Sun, 11 Mar 2007) | 1 line Fix resource leak reported in SF #1516995. ........ r54278 | collin.winter | 2007-03-11 18:55:54 -0700 (Sun, 11 Mar 2007) | 4 lines Patch #1678662: ftp.python.org does not exist. So the testcode in urllib.py must use a more stable FTP. Will backport. ........ r54280 | barry.warsaw | 2007-03-11 20:20:01 -0700 (Sun, 11 Mar 2007) | 8 lines Tokio Kikuchi's fix for SF bug #1629369; folding whitespace allowed in the display name of an email address, e.g. Foo \tBar Test case added by Barry. ........ r54282 | skip.montanaro | 2007-03-11 20:30:50 -0700 (Sun, 11 Mar 2007) | 4 lines Sane humans would call these invalid tests, but Andrew McNamara pointed out that given the inputs in these tests Excel does indeed produce the output these tests expect. Document that for future confused folks. ........ r54283 | martin.v.loewis | 2007-03-12 03:50:39 -0700 (Mon, 12 Mar 2007) | 2 lines Bug #1675511: Use -Kpic instead of -xcode=pic32 on Solaris/x86. ........ r54285 | martin.v.loewis | 2007-03-12 04:01:10 -0700 (Mon, 12 Mar 2007) | 2 lines Patch #1677862: Require a space or tab after import in .pth files. ........ r54287 | georg.brandl | 2007-03-12 06:17:36 -0700 (Mon, 12 Mar 2007) | 8 lines Backport from Py3k branch: Patch #1591665: implement the __dir__() special function lookup in PyObject_Dir. Had to change a few bits of the patch because classobjs and __methods__ are still in Py2.6. ........ r54288 | georg.brandl | 2007-03-12 07:30:05 -0700 (Mon, 12 Mar 2007) | 3 lines Bug #1678647: write a newline after printing an exception in any case, even when converting the value to a string failed. ........ r54290 | collin.winter | 2007-03-12 08:57:19 -0700 (Mon, 12 Mar 2007) | 1 line Patch #1678088: convert test_operations to use unittest, fold the result into test_dict. ........ r54291 | collin.winter | 2007-03-12 09:11:39 -0700 (Mon, 12 Mar 2007) | 3 lines Bug #742342: make Python stop segfaulting on infinitely-recursive reload()s. Fixed by patch #922167. Will backport. ........ r54292 | georg.brandl | 2007-03-12 09:15:09 -0700 (Mon, 12 Mar 2007) | 2 lines Typo fix. ........ r54295 | collin.winter | 2007-03-12 10:24:07 -0700 (Mon, 12 Mar 2007) | 1 line Patch #1670993: Refactor test_threadedtempfile.py to use unittest. ........ r54296 | tim.peters | 2007-03-12 11:07:52 -0700 (Mon, 12 Mar 2007) | 2 lines Whitespace normalization. ........ r54297 | tim.peters | 2007-03-12 11:09:22 -0700 (Mon, 12 Mar 2007) | 2 lines Set missing svn:eol-style property on text files. ........ r54315 | brett.cannon | 2007-03-12 19:34:09 -0700 (Mon, 12 Mar 2007) | 8 lines Add test.test_support.transient_internet . Returns a context manager that nests test.test_support.TransientResource context managers that capture exceptions raised when the Internet connection is flaky. Initially using in test_socket_ssl but should probably be expanded to cover any test that should not raise the captured exceptions if the Internet connection works. ........ r54316 | brett.cannon | 2007-03-12 20:05:40 -0700 (Mon, 12 Mar 2007) | 2 lines Fix a typo where the variable name was not updated. ........ r54318 | neal.norwitz | 2007-03-12 21:59:58 -0700 (Mon, 12 Mar 2007) | 1 line Add Jerry Seutter for a bunch of his recent patches refactoring tests ........ r54319 | neal.norwitz | 2007-03-12 22:07:14 -0700 (Mon, 12 Mar 2007) | 7 lines Add some other acks for recent checkins: Brian Leair - 922167 Tomer Filiba - 1591665 Jeremy Jones - 1192590 ........ r54321 | neal.norwitz | 2007-03-12 22:31:38 -0700 (Mon, 12 Mar 2007) | 9 lines Fix some style nits: * lines too long * wrong indentation * space after a function name * wrong function name in error string * simplifying some logic Also add an error check to PyDict_SetItemString. ........ r54322 | georg.brandl | 2007-03-13 00:23:16 -0700 (Tue, 13 Mar 2007) | 2 lines Typo and grammar fixes. ........ r54323 | georg.brandl | 2007-03-13 00:50:57 -0700 (Tue, 13 Mar 2007) | 2 lines Patch #1679379: add documentation for fnmatch.translate(). ........ r54325 | georg.brandl | 2007-03-13 00:57:51 -0700 (Tue, 13 Mar 2007) | 2 lines Patch #1642844: comments to clarify the complexobject constructor. ........ r54326 | georg.brandl | 2007-03-13 01:14:27 -0700 (Tue, 13 Mar 2007) | 3 lines Patch #1668100: urllib2 now correctly raises URLError instead of OSError if accessing a local file via the file:// protocol fails. ........ r54327 | georg.brandl | 2007-03-13 02:32:11 -0700 (Tue, 13 Mar 2007) | 4 lines Patch #1635454: the csv.DictWriter class now includes the offending field names in its exception message if you try to write a record with a dictionary containing fields not in the CSV field names list. ........ r54328 | georg.brandl | 2007-03-13 02:41:31 -0700 (Tue, 13 Mar 2007) | 3 lines Patch #1555098: use str.join() instead of repeated string concatenation in robotparser. ........ r54329 | georg.brandl | 2007-03-13 03:06:48 -0700 (Tue, 13 Mar 2007) | 3 lines Patch #1542681: add entries for "with", "as" and "CONTEXTMANAGERS" to pydoc's help keywords. ........ r54331 | georg.brandl | 2007-03-13 03:19:22 -0700 (Tue, 13 Mar 2007) | 3 lines Patch #1569798: fix a bug in distutils when building Python from a directory within sys.exec_prefix. ........ r54333 | martin.v.loewis | 2007-03-13 03:24:00 -0700 (Tue, 13 Mar 2007) | 4 lines Patch #1449244: Support Unicode strings in email.message.Message.{set_charset,get_content_charset}. Will backport. ........ r54335 | lars.gustaebel | 2007-03-13 03:47:19 -0700 (Tue, 13 Mar 2007) | 34 lines This is the implementation of POSIX.1-2001 (pax) format read/write support. The TarInfo class now contains all necessary logic to process and create tar header data which has been moved there from the TarFile class. The fromtarfile() method was added. The new path and linkpath properties are aliases for the name and linkname attributes in correspondence to the pax naming scheme. The TarFile constructor and classmethods now accept a number of keyword arguments which could only be set as attributes before (e.g. dereference, ignore_zeros). The encoding and pax_headers arguments were added for pax support. There is a new tarinfo keyword argument that allows using subclassed TarInfo objects in TarFile. The boolean TarFile.posix attribute is deprecated, because now three tar formats are supported. Instead, the desired format for writing is specified using the constants USTAR_FORMAT, GNU_FORMAT and PAX_FORMAT as the format keyword argument. This change affects TarInfo.tobuf() as well. The test suite has been heavily reorganized and partially rewritten. A new testtar.tar was added that contains sample data in many formats from 4 different tar programs. Some bugs and quirks that also have been fixed: Directory names do no longer have a trailing slash in TarInfo.name or TarFile.getnames(). Adding the same file twice does not create a hardlink file member. The TarFile constructor does no longer need a name argument. The TarFile._mode attribute was renamed to mode and contains either 'r', 'w' or 'a'. ........ r54336 | georg.brandl | 2007-03-13 05:34:25 -0700 (Tue, 13 Mar 2007) | 3 lines Bug #1622896: fix a rare corner case where the bz2 module raised an error in spite of a succesful compression. ........ r54338 | lars.gustaebel | 2007-03-13 08:47:07 -0700 (Tue, 13 Mar 2007) | 3 lines Quick fix for tests that fail on systems with an encoding other than 'iso8859-1'. ........ r54339 | georg.brandl | 2007-03-13 10:43:32 -0700 (Tue, 13 Mar 2007) | 4 lines Patch #1603688: ConfigParser.SafeConfigParser now checks values that are set for invalid interpolation sequences that would lead to errors on reading back those values. ........ r54341 | georg.brandl | 2007-03-13 11:15:41 -0700 (Tue, 13 Mar 2007) | 3 lines Patch #1581073: add a flag to textwrap that prevents the dropping of whitespace while wrapping. ........ r54343 | georg.brandl | 2007-03-13 11:24:40 -0700 (Tue, 13 Mar 2007) | 2 lines Patch #1605192: list allowed states in error messages for imaplib. ........ r54344 | georg.brandl | 2007-03-13 11:31:49 -0700 (Tue, 13 Mar 2007) | 4 lines Patch #1537850: tempfile.NamedTemporaryFile now has a "delete" parameter which can be set to False to prevent the default delete-on-close behavior. ........ r54345 | collin.winter | 2007-03-13 11:53:04 -0700 (Tue, 13 Mar 2007) | 9 lines Add acks for recent patch checkins: Arvin Schnell - 1668482 S?\195?\169bastien Martini - 1481079 Heiko Wundram - 1491866 Damon Kohler - 1545011 Peter Parente - 1599845 Bjorn Lindqvist - 1678662 ........ r54346 | georg.brandl | 2007-03-13 12:00:36 -0700 (Tue, 13 Mar 2007) | 2 lines Acks for recent patches. ........ r54347 | georg.brandl | 2007-03-13 12:18:18 -0700 (Tue, 13 Mar 2007) | 3 lines Fix a tab. ........ r54348 | georg.brandl | 2007-03-13 12:32:21 -0700 (Tue, 13 Mar 2007) | 4 lines Patch #1533909: the timeit module now accepts callables in addition to strings for the code to time and the setup code. Also added two convenience functions for instantiating a Timer and calling its methods. ........ r54352 | georg.brandl | 2007-03-13 13:02:57 -0700 (Tue, 13 Mar 2007) | 3 lines Patch #1530482: add pydoc.render_doc() which returns the documentation for a thing instead of paging it to stdout, which pydoc.doc() does. ........ r54357 | thomas.heller | 2007-03-13 13:42:52 -0700 (Tue, 13 Mar 2007) | 1 line Patch #1649190: Adding support for _Bool to ctypes as c_bool, by David Remahl. ........ r54358 | georg.brandl | 2007-03-13 13:46:32 -0700 (Tue, 13 Mar 2007) | 2 lines Patch #1444529: the builtin compile() now accepts keyword arguments. (backport) ........ r54359 | thomas.heller | 2007-03-13 14:01:39 -0700 (Tue, 13 Mar 2007) | 1 line Add versionadded marker for ctypes.c_bool. ........ r54360 | georg.brandl | 2007-03-13 14:08:15 -0700 (Tue, 13 Mar 2007) | 3 lines Patch #1393667: pdb now has a "run" command which restarts the debugged Python program, optionally with different arguments. ........ r54361 | georg.brandl | 2007-03-13 14:32:01 -0700 (Tue, 13 Mar 2007) | 3 lines Deprecate commands.getstatus(). ........ r54362 | georg.brandl | 2007-03-13 14:32:56 -0700 (Tue, 13 Mar 2007) | 2 lines NEWS entry for getstatus() deprecation. ........ r54363 | georg.brandl | 2007-03-13 14:58:44 -0700 (Tue, 13 Mar 2007) | 4 lines Patch #1429539: pdb now correctly initializes the __main__ module for the debugged script, which means that imports from __main__ work correctly now. ........ r54364 | georg.brandl | 2007-03-13 15:07:36 -0700 (Tue, 13 Mar 2007) | 4 lines Patch #957650: "%var%" environment variable references are now properly expanded in ntpath.expandvars(), also "~user" home directory references are recognized and handled on Windows. ........ r54365 | georg.brandl | 2007-03-13 15:16:30 -0700 (Tue, 13 Mar 2007) | 2 lines Patch #1194449: correctly detect unbound methods in pydoc. ........ r54367 | georg.brandl | 2007-03-13 15:49:43 -0700 (Tue, 13 Mar 2007) | 5 lines Patch #1185447: binascii.b2a_qp() now correctly quotes binary characters with ASCII value less than 32. Also, it correctly quotes dots only if they occur on a single line, as opposed to the previous behavior of quoting dots if they are the second character of any line. ........ r54368 | collin.winter | 2007-03-13 16:02:15 -0700 (Tue, 13 Mar 2007) | 1 line Inline PyImport_GetModulesReloading(). ........ r54371 | barry.warsaw | 2007-03-13 21:59:50 -0700 (Tue, 13 Mar 2007) | 6 lines SF bug #1582282; decode_header() incorrectly splits not-conformant RFC 2047-like headers where there is no whitespace between encoded words. This fix changes the matching regexp to include a trailing lookahead assertion that the closing ?= must be followed by whitespace, newline, or end-of-string. This also changes the regexp to add the MULTILINE flag. ........ r54372 | gregory.p.smith | 2007-03-14 00:17:40 -0700 (Wed, 14 Mar 2007) | 2 lines correct order and names of the less often used keyword parameters. ........ r54373 | gregory.p.smith | 2007-03-14 00:19:50 -0700 (Wed, 14 Mar 2007) | 5 lines Its time to stop listing (Unix, Windows) when we really mean "everything but Mac OS 9" now that nobody is likely to use Python on Mac OS 9 and most of the (Mac) platform items are all OS X special API specific since OS X is unixy enough for these modules to be available out of the box. ........ r54376 | georg.brandl | 2007-03-14 01:27:52 -0700 (Wed, 14 Mar 2007) | 4 lines Bug #767111: fix long-standing bug in urllib which caused an AttributeError instead of an IOError when the server's response didn't contain a valid HTTP status line. ........ r54378 | ziga.seilnacht | 2007-03-14 05:24:09 -0700 (Wed, 14 Mar 2007) | 4 lines Patch #1680015: Don't modify __slots__ tuple if it contains an unicode name. Remove a reference leak that happened if the name could not be converted to string. Will backport. ........ r54386 | martin.v.loewis | 2007-03-14 13:02:31 -0700 (Wed, 14 Mar 2007) | 3 lines Patch #1559413: Fix test_cmd_line if sys.executable contains a space. Will backport. ........ r54389 | brett.cannon | 2007-03-14 14:40:13 -0700 (Wed, 14 Mar 2007) | 3 lines Note how test_socket_ssl has various exceptions that deal with a flaky Net connection are silenced. ........ r54390 | brett.cannon | 2007-03-14 14:44:15 -0700 (Wed, 14 Mar 2007) | 2 lines Raise ResourceDenied in test_urllib2net when the Net connection goes bad. ........ r54391 | neal.norwitz | 2007-03-14 21:41:20 -0700 (Wed, 14 Mar 2007) | 1 line Wrap a long line and fix a typo (is -> if) ........ r54392 | georg.brandl | 2007-03-15 00:38:14 -0700 (Thu, 15 Mar 2007) | 3 lines Patch #1680978: consistently use "alive" instead of "active" in the thread lib doc. ........ r54394 | georg.brandl | 2007-03-15 00:41:30 -0700 (Thu, 15 Mar 2007) | 3 lines Patch #1681153: the wave module now closes a file object it opened if initialization failed. ........ r54397 | ziga.seilnacht | 2007-03-15 04:44:55 -0700 (Thu, 15 Mar 2007) | 3 lines Patch #1462488: prevent a segfault in object_reduce_ex() by splitting the implementation for __reduce__ and __reduce_ex__ into two separate functions. Fixes bug #931877. Will backport. ........ r54404 | collin.winter | 2007-03-15 21:11:30 -0700 (Thu, 15 Mar 2007) | 3 lines Patch #1642547: Fix an error/crash when encountering syntax errors in complex if statements. Will backport. ........ r54406 | georg.brandl | 2007-03-16 00:55:09 -0700 (Fri, 16 Mar 2007) | 5 lines Bug #1681228: the webbrowser module now correctly uses the default GNOME or KDE browser, depending on whether there is a session of one of those present. Also, it tries the Windows default browser before trying Mozilla variants. (backport) ........ r54407 | georg.brandl | 2007-03-16 01:22:40 -0700 (Fri, 16 Mar 2007) | 4 lines Patch #1273829: os.walk() now has a "followlinks" parameter. If set to True (which is not the default), it visits symlinks pointing to directories. ........ r54408 | georg.brandl | 2007-03-16 01:24:21 -0700 (Fri, 16 Mar 2007) | 2 lines Add \versionadded tag. ........ r54409 | georg.brandl | 2007-03-16 01:33:47 -0700 (Fri, 16 Mar 2007) | 2 lines RFE #1670167: fix in isinstance() docs. ........ r54412 | ziga.seilnacht | 2007-03-16 04:59:38 -0700 (Fri, 16 Mar 2007) | 3 lines Patch #1623563: allow __class__ assignment for classes with __slots__. The old and the new class are still required to have the same slot names, but the order in which they are specified is not relevant. ........ r54413 | ziga.seilnacht | 2007-03-16 05:11:11 -0700 (Fri, 16 Mar 2007) | 2 lines Whitespace cleanup. Also remove the empty lines from the previous check in. ........ r54414 | jeremy.hylton | 2007-03-16 07:49:11 -0700 (Fri, 16 Mar 2007) | 2 lines Remove warning: funcion declaration isn't a prototype ........ r54415 | jeremy.hylton | 2007-03-16 08:59:47 -0700 (Fri, 16 Mar 2007) | 11 lines Clean up formatting of this file. The file should now follow PEP 7, except that it uses 4 space indents (in the style of Py3k). This particular code would be really hard to read with the regular tab idents. Other changes: - reflow long lines - change multi-line conditionals to have test at end of line ........ r54417 | collin.winter | 2007-03-16 14:13:35 -0700 (Fri, 16 Mar 2007) | 1 line Patch #1676994: Refactor test_popen2 to use unittest. ........ r54418 | collin.winter | 2007-03-16 14:15:35 -0700 (Fri, 16 Mar 2007) | 1 line Remove test/output/test_popen2 (missed in r54417). ........ r54419 | collin.winter | 2007-03-16 15:16:08 -0700 (Fri, 16 Mar 2007) | 1 line Patch 1339796: add a relpath() function to os.path. ........ r54421 | georg.brandl | 2007-03-17 09:08:45 -0700 (Sat, 17 Mar 2007) | 5 lines Patch #1675423: PyComplex_AsCComplex() now tries to convert an object to complex using its __complex__() method before falling back to the __float__() method. Therefore, the functions in the cmath module now can operate on objects that define a __complex__() method. (backport) ........ r54423 | gregory.p.smith | 2007-03-17 15:33:35 -0700 (Sat, 17 Mar 2007) | 2 lines move note to the correct section ........ r54426 | georg.brandl | 2007-03-18 01:25:00 -0700 (Sun, 18 Mar 2007) | 2 lines Patch #1682878: the new socket methods are recv_into and recvfrom_into, not *_buf. ........ r54432 | georg.brandl | 2007-03-18 11:28:25 -0700 (Sun, 18 Mar 2007) | 2 lines Patch #1678339: test case for bug in difflib. ........ r54439 | collin.winter | 2007-03-19 11:52:08 -0700 (Mon, 19 Mar 2007) | 1 line Patch #1630118: add a SpooledTemporaryFile class to tempfile. ........ r54441 | georg.brandl | 2007-03-19 12:02:48 -0700 (Mon, 19 Mar 2007) | 2 lines Patch #1683328: fixes and enhancements for "unparse" demo. ........ r54456 | neal.norwitz | 2007-03-19 22:07:28 -0700 (Mon, 19 Mar 2007) | 1 line Add some doc that was left out from some change to platform.py ........ r54457 | neal.norwitz | 2007-03-19 22:08:23 -0700 (Mon, 19 Mar 2007) | 1 line Add a comment about 3k migration ........ r54458 | neal.norwitz | 2007-03-19 22:21:21 -0700 (Mon, 19 Mar 2007) | 1 line Get rid of deprecation warning when testing commands.getstatus() ........ r54459 | neal.norwitz | 2007-03-19 22:23:09 -0700 (Mon, 19 Mar 2007) | 4 lines Try backing out 54407 to see if it corrects the problems on the Windows buildbots. This rev was backported, so we will need to keep both branches in sync, pending the outcome of the test after this checkin. ........ r54460 | neal.norwitz | 2007-03-19 23:13:25 -0700 (Mon, 19 Mar 2007) | 1 line Try to make this test more resistant to dropping from previous runs (ie, files that may exist but cause the test to fail). Should be backported (assuming it works :-) ........ r54461 | neal.norwitz | 2007-03-19 23:16:26 -0700 (Mon, 19 Mar 2007) | 1 line Try to make this test more resistant to dropping from previous runs (ie, files that may exist but cause the test to fail). Should be backported (assuming it works :-) ........ r54462 | neal.norwitz | 2007-03-19 23:53:17 -0700 (Mon, 19 Mar 2007) | 5 lines Try to be a little more resilient to errors. This might help the test pass, but my guess is that it won't. I'm guessing that some other test is leaving this file open which means it can't be removed under Windows AFAIK. ........ r54463 | neal.norwitz | 2007-03-20 01:14:57 -0700 (Tue, 20 Mar 2007) | 8 lines Try to get test_urllib to pass on Windows by closing the file. I'm guessing that's the problem. h.getfile() must be called *after* h.getreply() and the fp can be None. I'm not entirely convinced this is the best fix (or even correct). The buildbots will tell us if things improve or not. I don't know if this needs to be backported (assuming it actually works). ........ r54465 | raymond.hettinger | 2007-03-20 14:27:24 -0700 (Tue, 20 Mar 2007) | 1 line Extend work on rev 52962 and 53829 eliminating redundant PyObject_Hash() calls and fixing set/dict interoperability. ........ r54468 | georg.brandl | 2007-03-20 16:05:14 -0700 (Tue, 20 Mar 2007) | 2 lines Fix for glob.py if filesystem encoding is None. ........ r54479 | neal.norwitz | 2007-03-20 23:39:48 -0700 (Tue, 20 Mar 2007) | 1 line Remove unused file spotted by Paul Hankin ........ r54480 | georg.brandl | 2007-03-21 02:00:39 -0700 (Wed, 21 Mar 2007) | 3 lines Patch #1682205: a TypeError while unpacking an iterable is no longer masked by a generic one with the message "unpack non-sequence". ........ r54482 | georg.brandl | 2007-03-21 02:10:29 -0700 (Wed, 21 Mar 2007) | 2 lines New test for rev. 54407 which only uses directories under TESTFN. ........ r54483 | georg.brandl | 2007-03-21 02:16:53 -0700 (Wed, 21 Mar 2007) | 2 lines Patch #1684834: document some utility C API functions. ........ r54485 | georg.brandl | 2007-03-21 04:51:25 -0700 (Wed, 21 Mar 2007) | 2 lines Fix #1684254: split BROWSER contents with shlex to avoid displaying 'URL'. ........ r54487 | andrew.kuchling | 2007-03-21 07:32:43 -0700 (Wed, 21 Mar 2007) | 1 line Add comments on maintenance of this file ........ r54489 | andrew.kuchling | 2007-03-21 09:57:32 -0700 (Wed, 21 Mar 2007) | 1 line Fix sentence, and fix typo in example ........ r54490 | andrew.kuchling | 2007-03-21 09:59:20 -0700 (Wed, 21 Mar 2007) | 1 line Put code examples at left margin instead of indenting them ........ r54491 | facundo.batista | 2007-03-21 12:41:24 -0700 (Wed, 21 Mar 2007) | 1 line Minor clarification, saying that blocking means no timeout (from bug #882297) ........ r54492 | ziga.seilnacht | 2007-03-21 13:07:56 -0700 (Wed, 21 Mar 2007) | 2 lines Bug #1675967: re patterns pickled with older Python versions can now be unpickled. Will backport. ........ r54495 | raymond.hettinger | 2007-03-21 13:33:57 -0700 (Wed, 21 Mar 2007) | 1 line Add test and fix for fromkeys() optional argument. ........ r54524 | georg.brandl | 2007-03-22 01:05:45 -0700 (Thu, 22 Mar 2007) | 2 lines Bug #1685704: use -m switch in timeit docs. ........ r54533 | thomas.heller | 2007-03-22 12:44:31 -0700 (Thu, 22 Mar 2007) | 5 lines Back out "Patch #1643874: memory leak in ctypes fixed." The code in this patch leaves no way to give up the ownership of a BSTR instance. ........ r54538 | thomas.heller | 2007-03-22 13:34:37 -0700 (Thu, 22 Mar 2007) | 2 lines Explain the purpose of the b_needsfree flag (forward ported from release25-maint). ........ r54539 | guido.van.rossum | 2007-03-22 21:58:42 -0700 (Thu, 22 Mar 2007) | 12 lines - Bug #1683368: The object.__init__() and object.__new__() methods are now stricter in rejecting excess arguments. The only time when either allows excess arguments is when it is not overridden and the other one is. For backwards compatibility, when both are overridden, it is a deprecation warning (for now; maybe a Py3k warning later). When merging this into 3.0, the warnings should become errors. Note: without the change to string.py, lots of spurious warnings happen. What's going on there? ........ r54540 | neal.norwitz | 2007-03-22 22:17:23 -0700 (Thu, 22 Mar 2007) | 1 line Add Mark Dickinson for SF # 1675423. ........ r54541 | martin.v.loewis | 2007-03-23 03:35:49 -0700 (Fri, 23 Mar 2007) | 3 lines Patch #1686451: Fix return type for PySequence_{Count,Index,Fast_GET_SIZE}. Will backport. ........ r54543 | martin.v.loewis | 2007-03-23 06:27:15 -0700 (Fri, 23 Mar 2007) | 3 lines Bug #978833: Revert r50844, as it broke _socketobject.dup. Will backport. ........ r54545 | guido.van.rossum | 2007-03-23 11:53:03 -0700 (Fri, 23 Mar 2007) | 8 lines Add a type.__init__() method that enforces the same signature as type.__new__(), and then calls object.__init__(cls), just to be anal. This allows us to restore the code in string.py's _TemplateMetaclass that called super(...).__init__(name, bases, dct), which I commented out yesterday since it broke due to the stricter argument checking added to object.__init__(). ........ r54546 | facundo.batista | 2007-03-23 11:54:07 -0700 (Fri, 23 Mar 2007) | 4 lines Added a 'create_connect()' function to socket.py, which creates a connection with an optional timeout, and modified httplib.py to use this function in HTTPConnection. Applies patch 1676823. ........ r54547 | guido.van.rossum | 2007-03-23 12:39:01 -0700 (Fri, 23 Mar 2007) | 2 lines Add note about type.__init__(). ........ r54553 | thomas.heller | 2007-03-23 12:55:27 -0700 (Fri, 23 Mar 2007) | 5 lines Prevent creation (followed by a segfault) of array types when the size overflows the valid Py_ssize_t range. Check return values of PyMem_Malloc. Will backport to release25-maint. ........ r54555 | facundo.batista | 2007-03-23 13:23:08 -0700 (Fri, 23 Mar 2007) | 6 lines Surrounded with try/finally to socket's default timeout setting changes in the tests, so failing one test won't produce strange results in others. Also relaxed the timeout settings in the test (where actually the value didn't mean anything). ........ r54556 | collin.winter | 2007-03-23 15:24:39 -0700 (Fri, 23 Mar 2007) | 1 line Make test_relpath() pass on Windows. ........ r54559 | ziga.seilnacht | 2007-03-24 07:24:26 -0700 (Sat, 24 Mar 2007) | 6 lines Patch #1489771: update syntax rules in Python Reference Manual. Python 2.5 added support for explicit relative import statements and yield expressions, which were missing in the manual. Also fix grammar productions that used the names from the Grammar file, markup that broke the generated grammar.txt, and wrap some lines that broke the pdf output. Will backport. ........ r54565 | georg.brandl | 2007-03-24 15:20:34 -0700 (Sat, 24 Mar 2007) | 2 lines Remove typo accent. ........ r54566 | georg.brandl | 2007-03-24 15:27:56 -0700 (Sat, 24 Mar 2007) | 2 lines Revert accidental change. ........ r54567 | brett.cannon | 2007-03-24 18:32:36 -0700 (Sat, 24 Mar 2007) | 3 lines Change the docs to no longer claim that unittest is preferred over doctest for regression tests. ........ r54568 | facundo.batista | 2007-03-24 18:53:21 -0700 (Sat, 24 Mar 2007) | 4 lines Redone the tests, using the infrastructure already present for threading and socket serving. ........ r54570 | facundo.batista | 2007-03-24 20:20:05 -0700 (Sat, 24 Mar 2007) | 3 lines Closing the HTTP connection after each test, and listening more. ........ r54572 | georg.brandl | 2007-03-25 11:44:35 -0700 (Sun, 25 Mar 2007) | 2 lines Markup fix. ........ r54573 | georg.brandl | 2007-03-25 12:04:55 -0700 (Sun, 25 Mar 2007) | 2 lines Markup fix. ........ r54580 | facundo.batista | 2007-03-26 13:18:31 -0700 (Mon, 26 Mar 2007) | 5 lines Added an optional timeout to FTP class. Also I started a test_ftplib.py file to test the ftp lib (right now I included a basic test, the timeout one, and nothing else). ........ r54581 | georg.brandl | 2007-03-26 13:28:28 -0700 (Mon, 26 Mar 2007) | 2 lines Some nits. ........ r54582 | facundo.batista | 2007-03-26 13:56:09 -0700 (Mon, 26 Mar 2007) | 4 lines Forgot to add the file before the previous commit, here go the ftplib tests. ........ r54585 | facundo.batista | 2007-03-27 11:23:21 -0700 (Tue, 27 Mar 2007) | 5 lines Added an optional timeout to poplib.POP3. Also created a test_poplib.py file with a basic test and the timeout ones. Docs are also updated. ........ r54586 | facundo.batista | 2007-03-27 11:50:29 -0700 (Tue, 27 Mar 2007) | 3 lines The basic test cases of poplib.py. ........ r54594 | facundo.batista | 2007-03-27 20:45:20 -0700 (Tue, 27 Mar 2007) | 4 lines Bug 1688393. Adds a control of negative values in socket.recvfrom, which caused an ugly crash. ........ r54599 | facundo.batista | 2007-03-28 11:25:54 -0700 (Wed, 28 Mar 2007) | 5 lines Added timeout to smtplib (to SMTP and SMTP_SSL). Also created the test_smtplib.py file, with a basic test and the timeout ones. Docs are updated too. ........ r54603 | collin.winter | 2007-03-28 16:34:06 -0700 (Wed, 28 Mar 2007) | 3 lines Consolidate patches #1690164, 1683397, and 1690169, all of which refactor XML-related test suites. The patches are applied together because they use a common output/xmltests file. Thanks to Jerry Seutter for all three patches. ........ r54604 | collin.winter | 2007-03-28 19:28:16 -0700 (Wed, 28 Mar 2007) | 1 line Make test_zipfile clean up its temporary files properly. ........ r54605 | georg.brandl | 2007-03-29 00:41:32 -0700 (Thu, 29 Mar 2007) | 2 lines These are actually methods. ........ r54606 | georg.brandl | 2007-03-29 05:42:07 -0700 (Thu, 29 Mar 2007) | 4 lines In Windows' time.clock(), when QueryPerformanceFrequency() fails, the C lib's clock() is used, but it must be divided by CLOCKS_PER_SEC as for the POSIX implementation (thanks to #pypy). ........ r54608 | facundo.batista | 2007-03-29 11:22:35 -0700 (Thu, 29 Mar 2007) | 5 lines Added timout parameter to telnetlib.Telnet. Also created test_telnetlib.py with a basic test and timeout ones. Docs are also updated. ........ r54613 | facundo.batista | 2007-03-30 06:00:35 -0700 (Fri, 30 Mar 2007) | 4 lines Added the posibility to pass the timeout to FTP.connect, not only when instantiating the class. Docs and tests are updated. ........ r54614 | collin.winter | 2007-03-30 07:01:25 -0700 (Fri, 30 Mar 2007) | 1 line Bug #1688274: add documentation for C-level class objects. ........ r54615 | marc-andre.lemburg | 2007-03-30 08:01:42 -0700 (Fri, 30 Mar 2007) | 4 lines Bump the patch level version of distutils since there were a few bug fixes since the 2.5.0 release. ........ r54617 | georg.brandl | 2007-03-30 08:49:05 -0700 (Fri, 30 Mar 2007) | 2 lines Markup fix. ........ r54618 | georg.brandl | 2007-03-30 10:39:39 -0700 (Fri, 30 Mar 2007) | 2 lines Label name fix. ........ r54619 | georg.brandl | 2007-03-30 10:47:21 -0700 (Fri, 30 Mar 2007) | 2 lines Duplicate label fix. ........ r54620 | georg.brandl | 2007-03-30 10:48:39 -0700 (Fri, 30 Mar 2007) | 2 lines Markup fix. ........ r54623 | andrew.kuchling | 2007-03-30 11:00:15 -0700 (Fri, 30 Mar 2007) | 1 line Add item. (Oops, accidentally checked this in on my branch) ........ r54624 | georg.brandl | 2007-03-30 12:01:38 -0700 (Fri, 30 Mar 2007) | 2 lines Duplicate label fix. ........ r54625 | georg.brandl | 2007-03-30 12:14:02 -0700 (Fri, 30 Mar 2007) | 2 lines Markup fix. ........ r54629 | georg.brandl | 2007-03-31 03:17:31 -0700 (Sat, 31 Mar 2007) | 2 lines repair string literal. ........ r54630 | georg.brandl | 2007-03-31 04:54:58 -0700 (Sat, 31 Mar 2007) | 2 lines Markup fix. ........ r54631 | georg.brandl | 2007-03-31 04:58:36 -0700 (Sat, 31 Mar 2007) | 2 lines Duplicate label fix. ........ r54632 | georg.brandl | 2007-03-31 04:59:54 -0700 (Sat, 31 Mar 2007) | 2 lines Typo fix. ........ r54633 | neal.norwitz | 2007-03-31 11:54:18 -0700 (Sat, 31 Mar 2007) | 1 line Fix method names. Will backport. ........ r54634 | georg.brandl | 2007-03-31 11:56:11 -0700 (Sat, 31 Mar 2007) | 4 lines Bug #1655392: don't add -L/usr/lib/pythonX.Y/config to the LDFLAGS returned by python-config if Python was built with --enable-shared because that prevented the shared library from being used. ........ r54637 | collin.winter | 2007-03-31 12:31:34 -0700 (Sat, 31 Mar 2007) | 1 line Shut up an occaisonal buildbot error due to test files being left around. ........ r54644 | neal.norwitz | 2007-04-01 11:24:22 -0700 (Sun, 01 Apr 2007) | 11 lines SF #1685563, MSVCCompiler creates redundant and long PATH strings If MSVCCompiler.initialize() was called multiple times, the path would get duplicated. On Windows, this is a problem because the path is limited to 4k. There's no benefit in adding a path multiple times, so prevent that from occuring. We also normalize the path before checking for duplicates so things like /a and /a/ won't both be stored. Will backport. ........ r54646 | brett.cannon | 2007-04-01 11:47:27 -0700 (Sun, 01 Apr 2007) | 8 lines time.strptime's caching of its locale object was being recreated when the locale changed but not used during the function call it was recreated during. The test in this checkin is untested (OS X does not have the proper locale support for me to test), although the fix for the bug this deals with was tested by the OP (#1290505). Once the buildbots verify the test at least doesn't fail it becomes a backport candidate. ........ r54647 | brett.cannon | 2007-04-01 12:46:19 -0700 (Sun, 01 Apr 2007) | 3 lines Fix the test for recreating the locale cache object by not worrying about if one of the test locales cannot be set. ........ r54649 | georg.brandl | 2007-04-01 14:29:15 -0700 (Sun, 01 Apr 2007) | 2 lines Fix a lot of markup and meta-information glitches. ........ r54650 | georg.brandl | 2007-04-01 14:39:52 -0700 (Sun, 01 Apr 2007) | 2 lines Another fix. ........ r54651 | georg.brandl | 2007-04-01 15:39:10 -0700 (Sun, 01 Apr 2007) | 2 lines Lots of explicit class names for method and member descs. ........ r54652 | georg.brandl | 2007-04-01 15:40:12 -0700 (Sun, 01 Apr 2007) | 2 lines Explicit class names. ........ r54653 | georg.brandl | 2007-04-01 15:47:31 -0700 (Sun, 01 Apr 2007) | 2 lines Some semantic fixes. ........ r54654 | georg.brandl | 2007-04-01 16:29:10 -0700 (Sun, 01 Apr 2007) | 2 lines Remove bogus entry. ........ r54655 | georg.brandl | 2007-04-01 16:31:30 -0700 (Sun, 01 Apr 2007) | 2 lines Fix the class name of strings. ........ r54658 | raymond.hettinger | 2007-04-02 10:29:30 -0700 (Mon, 02 Apr 2007) | 1 line SF #1693079: Cannot save empty array in shelve ........ r54663 | raymond.hettinger | 2007-04-02 15:54:21 -0700 (Mon, 02 Apr 2007) | 3 lines Array module's buffer interface can now handle empty arrays. ........ r54664 | guido.van.rossum | 2007-04-02 16:55:37 -0700 (Mon, 02 Apr 2007) | 5 lines Fix warnings about object.__init__() signature. Two (test_array and test_descr) were bug IMO; the third (copy_reg) is a work-around which recognizes that object.__init__() doesn't do anything. ........ r54666 | raymond.hettinger | 2007-04-02 17:02:11 -0700 (Mon, 02 Apr 2007) | 1 line SF 1602378 Clarify docstrings for bisect ........ r54668 | raymond.hettinger | 2007-04-02 18:39:43 -0700 (Mon, 02 Apr 2007) | 3 lines SF #1382213: Tutorial section 9.5.1 ignores MRO for new-style classes ........ r54669 | matthias.klose | 2007-04-02 21:35:59 -0700 (Mon, 02 Apr 2007) | 4 lines - Fix an off-by-one bug in locale.strxfrm(). patch taken from http://bugs.debian.org/416934. ........ r54671 | georg.brandl | 2007-04-03 00:04:27 -0700 (Tue, 03 Apr 2007) | 9 lines Fix the strange case of \begin{methoddesc}[NNTP]{...} where \ifx#1\@undefined ended up comparing N and N, therefore executing the true part of the conditional, blowing up at \@undefined. ........ r54672 | facundo.batista | 2007-04-03 07:05:08 -0700 (Tue, 03 Apr 2007) | 4 lines Now using unittest for the tests infraestructure. Also split the tests in those who need the network, and that who doesn't. ........ r54673 | walter.doerwald | 2007-04-03 09:08:10 -0700 (Tue, 03 Apr 2007) | 4 lines Move the functionality for catching warnings in test_warnings.py into a separate class to that reusing the functionality in test_structmembers.py doesn't rerun the tests from test_warnings.py. ........ r54674 | walter.doerwald | 2007-04-03 09:16:24 -0700 (Tue, 03 Apr 2007) | 2 lines Document that CatchWarningTests is reused by test_structmembers.py. ........ r54675 | walter.doerwald | 2007-04-03 09:53:43 -0700 (Tue, 03 Apr 2007) | 4 lines Add tests for the filename. Test that the stacklevel is handled correctly. ........ r54676 | facundo.batista | 2007-04-03 10:29:48 -0700 (Tue, 03 Apr 2007) | 6 lines Added a SSL server to test_socket_ssl.py to be able to test locally. Now, it checks if have openssl available and run those specific tests (it starts openssl at the beggining of all the tests and then kills it at the end). ........ r54677 | walter.doerwald | 2007-04-03 11:33:29 -0700 (Tue, 03 Apr 2007) | 6 lines Implement a contextmanager test.test_support.catch_warning that can be used to catch the last warning issued by the warning framework. Change test_warnings.py and test_structmembers.py to use this new contextmanager. ........ r54678 | facundo.batista | 2007-04-03 14:15:34 -0700 (Tue, 03 Apr 2007) | 4 lines Changed the whole structure of startup and checking if the server is available. Hope to not get more false alarms. ........ r54681 | facundo.batista | 2007-04-04 07:10:40 -0700 (Wed, 04 Apr 2007) | 4 lines Fixed the way that the .pem files are looked for, and changed how to kill the process in win32 to use the _handle attribute. ........ r54682 | guido.van.rossum | 2007-04-04 10:43:02 -0700 (Wed, 04 Apr 2007) | 4 lines Fix a race condition in this test -- instead of assuming that it will take the test server thread at most 0.5 seconds to get ready, use an event variable. ........ r54683 | collin.winter | 2007-04-04 11:14:17 -0700 (Wed, 04 Apr 2007) | 1 line Clean up imports. ........ r54684 | collin.winter | 2007-04-04 11:16:24 -0700 (Wed, 04 Apr 2007) | 1 line Stop using test_support.verify(). ........ r54685 | martin.v.loewis | 2007-04-04 11:30:36 -0700 (Wed, 04 Apr 2007) | 2 lines Bug #1686475: Support stat'ing open files on Windows again. Will backport to 2.5. ........ r54687 | collin.winter | 2007-04-04 11:33:40 -0700 (Wed, 04 Apr 2007) | 1 line Make test_getopt use unittest. ........ r54688 | collin.winter | 2007-04-04 11:36:30 -0700 (Wed, 04 Apr 2007) | 1 line Make test_softspace use unittest. ........ r54689 | ziga.seilnacht | 2007-04-04 11:38:47 -0700 (Wed, 04 Apr 2007) | 2 lines Fix WalkTests.test_traversal() on Windows. The cleanup in MakedirTests.setUp() can now be removed. ........ r54695 | raymond.hettinger | 2007-04-05 11:00:03 -0700 (Thu, 05 Apr 2007) | 3 lines Bug #1563759: struct.unpack doens't support buffer protocol objects ........ r54697 | collin.winter | 2007-04-05 13:05:07 -0700 (Thu, 05 Apr 2007) | 1 line Convert test_long_future to use unittest. ........ r54698 | collin.winter | 2007-04-05 13:08:56 -0700 (Thu, 05 Apr 2007) | 1 line Convert test_normalization to use unittest. ........ r54699 | andrew.kuchling | 2007-04-05 18:11:58 -0700 (Thu, 05 Apr 2007) | 1 line Some grammar fixes ........ r54704 | collin.winter | 2007-04-06 12:27:40 -0700 (Fri, 06 Apr 2007) | 1 line Convert test_stringprep to use unittest. ........ r54705 | collin.winter | 2007-04-06 12:32:32 -0700 (Fri, 06 Apr 2007) | 1 line Import cleanup in test_crypt. ........ r54706 | collin.winter | 2007-04-06 13:00:05 -0700 (Fri, 06 Apr 2007) | 1 line Convert test_gc to use unittest. ........ r54707 | collin.winter | 2007-04-06 13:03:11 -0700 (Fri, 06 Apr 2007) | 1 line Convert test_module to use unittest. ........ r54711 | collin.winter | 2007-04-06 21:40:43 -0700 (Fri, 06 Apr 2007) | 1 line Convert test_fileinput to use unittest. ........ r54712 | brett.cannon | 2007-04-07 21:29:32 -0700 (Sat, 07 Apr 2007) | 5 lines Doc that file.next() has undefined behaviour when called on a file opened with 'w'. Closes bug #1569057. To be backported once 2.5 branch is unfrozen. ........ r54726 | vinay.sajip | 2007-04-09 09:16:10 -0700 (Mon, 09 Apr 2007) | 1 line Added optional timeout to SocketHandler.makeSocket (SF #1695948) ........ r54727 | ziga.seilnacht | 2007-04-09 12:10:29 -0700 (Mon, 09 Apr 2007) | 3 lines Patch #1695862: remove old test directory that causes test_urllib failures on Windows buildbots. The change is a one time fix and will be removed after a successful buildbot run. ........ r54729 | facundo.batista | 2007-04-09 20:00:37 -0700 (Mon, 09 Apr 2007) | 3 lines Minor fix to the tests pass ok even with -O. ........ r54730 | collin.winter | 2007-04-09 21:44:49 -0700 (Mon, 09 Apr 2007) | 1 line Typo fix. ........ r54732 | facundo.batista | 2007-04-10 05:58:45 -0700 (Tue, 10 Apr 2007) | 5 lines General clean-up. Lot of margin corrections, comments, some typos. Exceptions now are raised in the new style. And a mockup class is now also new style. Thanks Santiago Pereson. ........ r54741 | georg.brandl | 2007-04-10 14:39:38 -0700 (Tue, 10 Apr 2007) | 2 lines Repair a duplicate label and some obsolete uses of \setindexsubitem. ........ r54746 | andrew.kuchling | 2007-04-11 06:39:00 -0700 (Wed, 11 Apr 2007) | 1 line Add window.chgat() method, submitted via e-mail by Fabian Kreutz ........ r54747 | andrew.kuchling | 2007-04-11 06:42:25 -0700 (Wed, 11 Apr 2007) | 1 line Point readers at the patch submission instructions ........ r54748 | andrew.kuchling | 2007-04-11 06:47:13 -0700 (Wed, 11 Apr 2007) | 1 line Describe undocumented third argument to touchline() ........ r54757 | georg.brandl | 2007-04-11 10:16:24 -0700 (Wed, 11 Apr 2007) | 3 lines Add some missing NULL checks which trigger crashes on low-memory conditions. Found by Victor Stinner. Will backport when 2.5 branch is unfrozen. ........ r54760 | raymond.hettinger | 2007-04-11 11:40:58 -0700 (Wed, 11 Apr 2007) | 1 line SF 1191699: Make slices picklable ........ r54762 | georg.brandl | 2007-04-11 12:25:11 -0700 (Wed, 11 Apr 2007) | 2 lines Exceptions are no longer old-style instances. Fix accordingly. ........ r54763 | georg.brandl | 2007-04-11 16:28:44 -0700 (Wed, 11 Apr 2007) | 2 lines Repair missing spaces after \UNIX. ........ r54772 | raymond.hettinger | 2007-04-11 21:10:00 -0700 (Wed, 11 Apr 2007) | 1 line SF 1193128: Let str.translate(None) be an identity transformation ........ r54784 | georg.brandl | 2007-04-12 00:01:19 -0700 (Thu, 12 Apr 2007) | 2 lines Patch #1698951: clarify deprecation message in rexec and Bastion ........ r54785 | ziga.seilnacht | 2007-04-12 01:46:51 -0700 (Thu, 12 Apr 2007) | 2 lines Patch #1695862: remove the cleanup code, now that Windows buildbots are green again. ........ r54786 | walter.doerwald | 2007-04-12 03:35:00 -0700 (Thu, 12 Apr 2007) | 3 lines Fix utf-8-sig incremental decoder, which didn't recognise a BOM when the first chunk fed to the decoder started with a BOM, but was longer than 3 bytes. ........ r54807 | barry.warsaw | 2007-04-13 11:47:14 -0700 (Fri, 13 Apr 2007) | 8 lines Port r54805 from python25-maint branch: Add code to read from master_fd in the parent, breaking when we get an OSError (EIO can occur on Linux) or there's no more data to read. Without this, test_pty.py can hang on the waitpid() because the child is blocking on the stdout write. This will definitely happen on Mac OS X and could potentially happen on other platforms. See the comment for details. ........ r54812 | kristjan.jonsson | 2007-04-13 15:07:33 -0700 (Fri, 13 Apr 2007) | 1 line Fix a bug when using the __lltrace__ opcode tracer, and a problem sith signed chars in frameobject.c which can occur with opcodes > 127 ........ r54814 | kristjan.jonsson | 2007-04-13 15:20:13 -0700 (Fri, 13 Apr 2007) | 1 line Fix potential crash in path manipulation on windows ........ r54816 | trent.mick | 2007-04-13 16:22:05 -0700 (Fri, 13 Apr 2007) | 4 lines Add the necessary dependency for the Windows VC6 build to ensure 'pythoncore' is built before '_ctypes' is attempted. Will backport to 2.5 once it is unfrozen for 2.5.1. ........ r54825 | neal.norwitz | 2007-04-13 22:25:50 -0700 (Fri, 13 Apr 2007) | 3 lines When __slots__ are set to a unicode string, make it work the same as setting a plain string, ie don't expand to single letter identifiers. ........ r54841 | neal.norwitz | 2007-04-16 00:37:55 -0700 (Mon, 16 Apr 2007) | 1 line SF #1701207, Fix bogus assertion (and test it!) ........ r54844 | collin.winter | 2007-04-16 15:10:32 -0700 (Mon, 16 Apr 2007) | 1 line Check the availability of the urlfetch resource earlier than before. ........ r54849 | martin.v.loewis | 2007-04-16 22:02:01 -0700 (Mon, 16 Apr 2007) | 2 lines Add Travis Oliphant. ........ r54873 | brett.cannon | 2007-04-18 20:44:17 -0700 (Wed, 18 Apr 2007) | 2 lines Silence a compiler warning about incompatible pointer types. ........ r54874 | neal.norwitz | 2007-04-18 22:52:37 -0700 (Wed, 18 Apr 2007) | 2 lines SF #1703270, add missing declaration in readline.c to avoid compiler warning. ........ r54875 | armin.rigo | 2007-04-19 07:44:48 -0700 (Thu, 19 Apr 2007) | 8 lines Revert r53997 as per http://mail.python.org/pipermail/python-dev/2007-March/071796.html . I've kept a couple of still-valid extra tests in test_descr, but didn't bother to sort through the new comments and refactorings added in r53997 to see if some of them could be kept. If so, they could go in a follow-up check-in. ........ r54876 | armin.rigo | 2007-04-19 07:56:48 -0700 (Thu, 19 Apr 2007) | 2 lines Fix a usage of the dangerous pattern decref - modify field - incref. ........ r54884 | neal.norwitz | 2007-04-19 22:20:38 -0700 (Thu, 19 Apr 2007) | 9 lines Add an optional address to copy the failure mails to. Detect a conflict in the only file that should have outstanding changes when this script is run. This doesn't matter on the trunk, but does when run on a branch. Trunk always has the date set to today in boilerplate.tex. Each time a release is cut with a different date, a conflict occurs. (We could copy a known good version, but then we would lose changes to this file.) ........ r54918 | georg.brandl | 2007-04-21 13:35:38 -0700 (Sat, 21 Apr 2007) | 3 lines Bug #1704790: bind name "sys" locally in __del__ method so that it is not cleared before __del__ is run. ........ r54920 | facundo.batista | 2007-04-21 18:18:56 -0700 (Sat, 21 Apr 2007) | 5 lines Added tests for other methods of SSL object. Now we cover all the object methods. This is the final step to close the #451607 bug. ........ r54927 | facundo.batista | 2007-04-23 10:08:31 -0700 (Mon, 23 Apr 2007) | 5 lines As specified in RFC 2616, 2xx code indicates that the client's request was successfully received, understood, and accepted. Now in these cases no error is raised. Also fixed tests. ........ r54929 | collin.winter | 2007-04-23 20:43:46 -0700 (Mon, 23 Apr 2007) | 1 line Convert PyUnit -> unittest. ........ r54931 | collin.winter | 2007-04-23 21:09:52 -0700 (Mon, 23 Apr 2007) | 1 line Remove code that hasn't been called in years. ........ r54932 | neal.norwitz | 2007-04-23 21:53:12 -0700 (Mon, 23 Apr 2007) | 1 line Fix SF #1703110, Incorrect example for add_password() (use uri, not host) ........ r54934 | georg.brandl | 2007-04-24 03:36:42 -0700 (Tue, 24 Apr 2007) | 2 lines Some new year updates. ........ r54938 | facundo.batista | 2007-04-24 06:54:38 -0700 (Tue, 24 Apr 2007) | 4 lines Added a comment about last change in urllib2.py (all 2xx responses are ok now). ........ r54939 | georg.brandl | 2007-04-24 08:10:09 -0700 (Tue, 24 Apr 2007) | 2 lines Bug #1705717: error in sys.argv docs. ........ r54941 | georg.brandl | 2007-04-24 08:27:13 -0700 (Tue, 24 Apr 2007) | 4 lines Bug #1706381: Specifying the SWIG option "-c++" in the setup.py file (as opposed to the command line) will now write file names ending in ".cpp" too. ........ r54944 | raymond.hettinger | 2007-04-24 15:13:43 -0700 (Tue, 24 Apr 2007) | 1 line Fix markup ........ r54945 | kristjan.jonsson | 2007-04-24 17:10:50 -0700 (Tue, 24 Apr 2007) | 1 line Merge change 54909 from release25-maint: Fix several minor issues discovered using code analysis in VisualStudio 2005 Team Edition ........ r54947 | kristjan.jonsson | 2007-04-24 17:17:39 -0700 (Tue, 24 Apr 2007) | 1 line Make pythoncore compile cleanly with VisualStudio 2005. Used an explicit typecast to get a 64 bit integer, and undefined the Yield macro that conflicts with winbase.h ........ r54948 | kristjan.jonsson | 2007-04-24 17:19:26 -0700 (Tue, 24 Apr 2007) | 1 line Remove obsolete comment. Importing of .dll files has been discontinued, only .pyd files supported on windows now. ........ r54949 | georg.brandl | 2007-04-24 23:24:59 -0700 (Tue, 24 Apr 2007) | 2 lines Patch #1698768: updated the "using Python on the Mac" intro. ........ r54951 | georg.brandl | 2007-04-24 23:25:55 -0700 (Tue, 24 Apr 2007) | 2 lines Markup fix. ........ r54953 | neal.norwitz | 2007-04-24 23:30:05 -0700 (Tue, 24 Apr 2007) | 3 lines Whitespace normalization. Ugh, we really need to do this more often. You might want to review this change as it's my first time. Be gentle. :-) ........ r54956 | collin.winter | 2007-04-25 10:29:52 -0700 (Wed, 25 Apr 2007) | 1 line Standardize on test.test_support.run_unittest() (as opposed to a mix of run_unittest() and run_suite()). Also, add functionality to run_unittest() that admits usage of unittest.TestLoader.loadTestsFromModule(). ........ r54957 | collin.winter | 2007-04-25 10:37:35 -0700 (Wed, 25 Apr 2007) | 1 line Remove functionality from test_datetime.test_main() that does reference count checking; 'regrtest.py -R' is the way to do this kind of testing. ........ r54958 | collin.winter | 2007-04-25 10:57:53 -0700 (Wed, 25 Apr 2007) | 1 line Change test_support.have_unicode to use True/False instead of 1/0. ........ r54959 | tim.peters | 2007-04-25 11:47:18 -0700 (Wed, 25 Apr 2007) | 2 lines Whitespace normalization. ........ r54960 | tim.peters | 2007-04-25 11:48:35 -0700 (Wed, 25 Apr 2007) | 2 lines Set missing svn:eol-style property on text files. ........ r54961 | collin.winter | 2007-04-25 11:54:36 -0700 (Wed, 25 Apr 2007) | 1 line Import and raise statement cleanup. ........ r54969 | collin.winter | 2007-04-25 13:41:34 -0700 (Wed, 25 Apr 2007) | 1 line Convert test_ossaudiodev to use unittest. ........ r54974 | collin.winter | 2007-04-25 14:50:25 -0700 (Wed, 25 Apr 2007) | 1 line Fix an issue related to the unittest conversion. ........ r54979 | fred.drake | 2007-04-25 21:42:19 -0700 (Wed, 25 Apr 2007) | 1 line fix some markup errors ........ r54982 | kristjan.jonsson | 2007-04-26 02:15:08 -0700 (Thu, 26 Apr 2007) | 1 line Export function sanitize_the_mode from fileobject.c as _PyFile_SanitizeMode(). Use this function in posixmodule.c when implementing fdopen(). This fixes test_subprocess.py for a VisualStudio 2005 compile. ........ r54983 | kristjan.jonsson | 2007-04-26 06:44:16 -0700 (Thu, 26 Apr 2007) | 1 line The locale "En" appears not to be valid on windows underi VisualStudio.2005. Added "English" to the test_locale.py to make the testsuite pass for that build ........ r54984 | steve.holden | 2007-04-26 07:23:12 -0700 (Thu, 26 Apr 2007) | 1 line Minor wording change on slicing aide-memoire. ........ r54985 | kristjan.jonsson | 2007-04-26 08:24:54 -0700 (Thu, 26 Apr 2007) | 1 line Accomodate 64 bit time_t in the _bsddb module. ........ Modified: python/branches/p3yk/Demo/parser/unparse.py ============================================================================== --- python/branches/p3yk/Demo/parser/unparse.py (original) +++ python/branches/p3yk/Demo/parser/unparse.py Fri Apr 27 21:54:29 2007 @@ -4,6 +4,19 @@ import cStringIO import os +def interleave(inter, f, seq): + """Call f on each item in seq, calling inter() in between. + """ + seq = iter(seq) + try: + f(seq.next()) + except StopIteration: + pass + else: + for x in seq: + inter() + f(x) + class Unparser: """Methods in this class recursively traverse an AST and output source code for the abstract syntax; original formatting @@ -63,26 +76,13 @@ def _Import(self, t): self.fill("import ") - first = True - for a in t.names: - if first: - first = False - else: - self.write(", ") - self.write(a.name) - if a.asname: - self.write(" as "+a.asname) + interleave(lambda: self.write(", "), self.dispatch, t.names) def _ImportFrom(self, t): self.fill("from ") self.write(t.module) self.write(" import ") - for i, a in enumerate(t.names): - if i == 0: - self.write(", ") - self.write(a.name) - if a.asname: - self.write(" as "+a.asname) + interleave(lambda: self.write(", "), self.dispatch, t.names) # XXX(jpe) what is level for? def _Assign(self, t): @@ -99,8 +99,9 @@ self.dispatch(t.value) def _Return(self, t): - self.fill("return ") + self.fill("return") if t.value: + self.write(" ") self.dispatch(t.value) def _Pass(self, t): @@ -138,18 +139,16 @@ self.write(",") def _Global(self, t): - self.fill("global") - for i, n in enumerate(t.names): - if i != 0: - self.write(",") - self.write(" " + n) + self.fill("global ") + interleave(lambda: self.write(", "), self.write, t.names) def _Yield(self, t): - self.fill("yield") + self.write("(") + self.write("yield") if t.value: - self.write(" (") + self.write(" ") self.dispatch(t.value) - self.write(")") + self.write(")") def _Raise(self, t): self.fill('raise ') @@ -188,8 +187,9 @@ self.leave() def _excepthandler(self, t): - self.fill("except ") + self.fill("except") if t.type: + self.write(" ") self.dispatch(t.type) if t.name: self.write(", ") @@ -289,9 +289,7 @@ def _List(self, t): self.write("[") - for e in t.elts: - self.dispatch(e) - self.write(", ") + interleave(lambda: self.write(", "), self.dispatch, t.elts) self.write("]") def _ListComp(self, t): @@ -318,30 +316,31 @@ self.dispatch(if_clause) def _IfExp(self, t): + self.write("(") self.dispatch(t.body) self.write(" if ") self.dispatch(t.test) - if t.orelse: - self.write(" else ") - self.dispatch(t.orelse) + self.write(" else ") + self.dispatch(t.orelse) + self.write(")") def _Dict(self, t): self.write("{") - for k,v in zip(t.keys, t.values): + def writem((k, v)): self.dispatch(k) - self.write(" : ") + self.write(": ") self.dispatch(v) - self.write(", ") + interleave(lambda: self.write(", "), writem, zip(t.keys, t.values)) self.write("}") def _Tuple(self, t): - if not t.elts: - self.write("()") - return self.write("(") - for e in t.elts: - self.dispatch(e) - self.write(", ") + if len(t.elts) == 1: + (elt,) = t.elts + self.dispatch(elt) + self.write(",") + else: + interleave(lambda: self.write(", "), self.dispatch, t.elts) self.write(")") unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"} @@ -357,7 +356,7 @@ def _BinOp(self, t): self.write("(") self.dispatch(t.left) - self.write(")" + self.binop[t.op.__class__.__name__] + "(") + self.write(" " + self.binop[t.op.__class__.__name__] + " ") self.dispatch(t.right) self.write(")") @@ -367,17 +366,15 @@ self.write("(") self.dispatch(t.left) for o, e in zip(t.ops, t.comparators): - self.write(") " +self.cmpops[o.__class__.__name__] + " (") + self.write(" " + self.cmpops[o.__class__.__name__] + " ") self.dispatch(e) self.write(")") boolops = {_ast.And: 'and', _ast.Or: 'or'} def _BoolOp(self, t): self.write("(") - self.dispatch(t.values[0]) - for v in t.values[1:]: - self.write(" %s " % self.boolops[t.op.__class__]) - self.dispatch(v) + s = " %s " % self.boolops[t.op.__class__] + interleave(lambda: self.write(s), self.dispatch, t.values) self.write(")") def _Attribute(self,t): @@ -433,10 +430,7 @@ self.dispatch(t.step) def _ExtSlice(self, t): - for i, d in enumerate(t.dims): - if i != 0: - self.write(': ') - self.dispatch(d) + interleave(lambda: self.write(', '), self.dispatch, t.dims) # others def _arguments(self, t): @@ -472,9 +466,14 @@ self.write(": ") self.dispatch(t.body) + def _alias(self, t): + self.write(t.name) + if t.asname: + self.write(" as "+t.asname) + def roundtrip(filename, output=sys.stdout): source = open(filename).read() - tree = compile(source, filename, "exec", 0x400) + tree = compile(source, filename, "exec", _ast.PyCF_ONLY_AST) Unparser(tree, output) Modified: python/branches/p3yk/Doc/api/abstract.tex ============================================================================== --- python/branches/p3yk/Doc/api/abstract.tex (original) +++ python/branches/p3yk/Doc/api/abstract.tex Fri Apr 27 21:54:29 2007 @@ -790,7 +790,7 @@ the Python statement \samp{del \var{o}[\var{i1}:\var{i2}]}. \end{cfuncdesc} -\begin{cfuncdesc}{int}{PySequence_Count}{PyObject *o, PyObject *value} +\begin{cfuncdesc}{Py_ssize_t}{PySequence_Count}{PyObject *o, PyObject *value} Return the number of occurrences of \var{value} in \var{o}, that is, return the number of keys for which \code{\var{o}[\var{key}] == \var{value}}. On failure, return \code{-1}. This is equivalent to @@ -804,7 +804,7 @@ expression \samp{\var{value} in \var{o}}. \end{cfuncdesc} -\begin{cfuncdesc}{int}{PySequence_Index}{PyObject *o, PyObject *value} +\begin{cfuncdesc}{Py_ssize_t}{PySequence_Index}{PyObject *o, PyObject *value} Return the first index \var{i} for which \code{\var{o}[\var{i}] == \var{value}}. On error, return \code{-1}. This is equivalent to the Python expression \samp{\var{o}.index(\var{value})}. @@ -854,7 +854,7 @@ \versionadded{2.3} \end{cfuncdesc} -\begin{cfuncdesc}{int}{PySequence_Fast_GET_SIZE}{PyObject *o} +\begin{cfuncdesc}{Py_ssize_t}{PySequence_Fast_GET_SIZE}{PyObject *o} Returns the length of \var{o}, assuming that \var{o} was returned by \cfunction{PySequence_Fast()} and that \var{o} is not \NULL. The size can also be gotten by calling Modified: python/branches/p3yk/Doc/api/concrete.tex ============================================================================== --- python/branches/p3yk/Doc/api/concrete.tex (original) +++ python/branches/p3yk/Doc/api/concrete.tex Fri Apr 27 21:54:29 2007 @@ -442,7 +442,9 @@ \begin{cfuncdesc}{double}{PyFloat_AsDouble}{PyObject *pyfloat} Return a C \ctype{double} representation of the contents of - \var{pyfloat}. + \var{pyfloat}. If \var{pyfloat} is not a Python floating point + object but has a \method{__float__} method, this method will first + be called to convert \var{pyfloat} into a float. \end{cfuncdesc} \begin{cfuncdesc}{double}{PyFloat_AS_DOUBLE}{PyObject *pyfloat} @@ -557,8 +559,11 @@ \end{cfuncdesc} \begin{cfuncdesc}{Py_complex}{PyComplex_AsCComplex}{PyObject *op} - Return the \ctype{Py_complex} value of the complex number - \var{op}. + Return the \ctype{Py_complex} value of the complex number \var{op}. + \versionchanged[If \var{op} is not a Python complex number object + but has a \method{__complex__} method, this method + will first be called to convert \var{op} to a Python + complex number object]{2.6} \end{cfuncdesc} @@ -2156,6 +2161,35 @@ \section{Other Objects \label{otherObjects}} +\subsection{Class Objects \label{classObjects}} + +\obindex{class} +Note that the class objects described here represent old-style classes, +which will go away in Python 3. When creating new types for extension +modules, you will want to work with type objects (section +\ref{typeObjects}). + +\begin{ctypedesc}{PyClassObject} + The C structure of the objects used to describe built-in classes. +\end{ctypedesc} + +\begin{cvardesc}{PyObject*}{PyClass_Type} + This is the type object for class objects; it is the same object as + \code{types.ClassType} in the Python layer. + \withsubitem{(in module types)}{\ttindex{ClassType}} +\end{cvardesc} + +\begin{cfuncdesc}{int}{PyClass_Check}{PyObject *o} + Return true if the object \var{o} is a class object, including + instances of types derived from the standard class object. Return + false in all other cases. +\end{cfuncdesc} + +\begin{cfuncdesc}{int}{PyClass_IsSubclass}{PyObject *klass, PyObject *base} + Return true if \var{klass} is a subclass of \var{base}. Return false in + all other cases. +\end{cfuncdesc} + \subsection{File Objects \label{fileObjects}} \obindex{file} Modified: python/branches/p3yk/Doc/api/init.tex ============================================================================== --- python/branches/p3yk/Doc/api/init.tex (original) +++ python/branches/p3yk/Doc/api/init.tex Fri Apr 27 21:54:29 2007 @@ -245,7 +245,7 @@ program name (set by \cfunction{Py_SetProgramName()} above) and some environment variables. The returned string consists of a series of directory names separated by a platform dependent delimiter - character. The delimiter character is \character{:} on \UNIX and Mac OS X, + character. The delimiter character is \character{:} on \UNIX{} and Mac OS X, \character{;} on Windows. The returned string points into static storage; the caller should not modify its value. The value is available to Python code as the list Modified: python/branches/p3yk/Doc/api/memory.tex ============================================================================== --- python/branches/p3yk/Doc/api/memory.tex (original) +++ python/branches/p3yk/Doc/api/memory.tex Fri Apr 27 21:54:29 2007 @@ -100,7 +100,9 @@ memory block is resized but is not freed, and the returned pointer is non-\NULL. Unless \var{p} is \NULL, it must have been returned by a previous call to \cfunction{PyMem_Malloc()} or - \cfunction{PyMem_Realloc()}. + \cfunction{PyMem_Realloc()}. If the request fails, + \cfunction{PyMem_Realloc()} returns \NULL{} and \var{p} remains a + valid pointer to the previous memory area. \end{cfuncdesc} \begin{cfuncdesc}{void}{PyMem_Free}{void *p} @@ -124,7 +126,8 @@ \begin{cfuncdesc}{\var{TYPE}*}{PyMem_Resize}{void *p, TYPE, size_t n} Same as \cfunction{PyMem_Realloc()}, but the memory block is resized to \code{(\var{n} * sizeof(\var{TYPE}))} bytes. Returns a pointer - cast to \ctype{\var{TYPE}*}. + cast to \ctype{\var{TYPE}*}. On return, \var{p} will be a pointer to + the new memory area, or \NULL{} in the event of failure. \end{cfuncdesc} \begin{cfuncdesc}{void}{PyMem_Del}{void *p} Modified: python/branches/p3yk/Doc/api/newtypes.tex ============================================================================== --- python/branches/p3yk/Doc/api/newtypes.tex (original) +++ python/branches/p3yk/Doc/api/newtypes.tex Fri Apr 27 21:54:29 2007 @@ -1316,7 +1316,7 @@ This field is inherited by static subtypes, but not by dynamic subtypes (subtypes created by a class statement); in the latter, - this field is always set to \cfunction{PyType_GenericAlloc()}, to + this field is always set to \cfunction{PyType_GenericAlloc}, to force a standard heap allocation strategy. That is also the recommended value for statically defined types. \end{cmemberdesc} Modified: python/branches/p3yk/Doc/api/utilities.tex ============================================================================== --- python/branches/p3yk/Doc/api/utilities.tex (original) +++ python/branches/p3yk/Doc/api/utilities.tex Fri Apr 27 21:54:29 2007 @@ -930,3 +930,94 @@ If there is an error in the format string, the \exception{SystemError} exception is set and \NULL{} returned. \end{cfuncdesc} + +\section{String conversion and formatting \label{string-formatting}} + +Functions for number conversion and formatted string output. + +\begin{cfuncdesc}{int}{PyOS_snprintf}{char *str, size_t size, + const char *format, \moreargs} +Output not more than \var{size} bytes to \var{str} according to the format +string \var{format} and the extra arguments. See the \UNIX{} man +page \manpage{snprintf}{2}. +\end{cfuncdesc} + +\begin{cfuncdesc}{int}{PyOS_vsnprintf}{char *str, size_t size, + const char *format, va_list va} +Output not more than \var{size} bytes to \var{str} according to the format +string \var{format} and the variable argument list \var{va}. \UNIX{} +man page \manpage{vsnprintf}{2}. +\end{cfuncdesc} + +\cfunction{PyOS_snprintf} and \cfunction{PyOS_vsnprintf} wrap the +Standard C library functions \cfunction{snprintf()} and +\cfunction{vsnprintf()}. Their purpose is to guarantee consistent +behavior in corner cases, which the Standard C functions do not. + +The wrappers ensure that \var{str}[\var{size}-1] is always +\character{\textbackslash0} upon return. They never write more than +\var{size} bytes (including the trailing \character{\textbackslash0} +into str. Both functions require that \code{\var{str} != NULL}, +\code{\var{size} > 0} and \code{\var{format} != NULL}. + +If the platform doesn't have \cfunction{vsnprintf()} and the buffer +size needed to avoid truncation exceeds \var{size} by more than 512 +bytes, Python aborts with a \var{Py_FatalError}. + +The return value (\var{rv}) for these functions should be interpreted +as follows: + +\begin{itemize} + +\item When \code{0 <= \var{rv} < \var{size}}, the output conversion + was successful and \var{rv} characters were written to \var{str} + (excluding the trailing \character{\textbackslash0} byte at + \var{str}[\var{rv}]). + +\item When \code{\var{rv} >= \var{size}}, the output conversion was + truncated and a buffer with \code{\var{rv} + 1} bytes would have + been needed to succeed. \var{str}[\var{size}-1] is + \character{\textbackslash0} in this case. + +\item When \code{\var{rv} < 0}, ``something bad happened.'' + \var{str}[\var{size}-1] is \character{\textbackslash0} in this case + too, but the rest of \var{str} is undefined. The exact cause of the + error depends on the underlying platform. + +\end{itemize} + +The following functions provide locale-independent string to number +conversions. + +\begin{cfuncdesc}{double}{PyOS_ascii_strtod}{const char *nptr, char **endptr} +Convert a string to a \ctype{double}. This function behaves like the +Standard C function \cfunction{strtod()} does in the C locale. It does +this without changing the current locale, since that would not be +thread-safe. + +\cfunction{PyOS_ascii_strtod} should typically be used for reading +configuration files or other non-user input that should be locale +independent. \versionadded{2.4} + +See the \UNIX{} man page \manpage{strtod}{2} for details. + +\end{cfuncdesc} + +\begin{cfuncdesc}{char *}{PyOS_ascii_formatd}{char *buffer, size_t buf_len, + const char *format, double d} +Convert a \ctype{double} to a string using the \character{.} as the +decimal separator. \var{format} is a \cfunction{printf()}-style format +string specifying the number format. Allowed conversion characters are +\character{e}, \character{E}, \character{f}, \character{F}, +\character{g} and \character{G}. + +The return value is a pointer to \var{buffer} with the converted +string or NULL if the conversion failed. \versionadded{2.4} +\end{cfuncdesc} + +\begin{cfuncdesc}{double}{PyOS_ascii_atof}{const char *nptr} +Convert a string to a \ctype{double} in a locale-independent +way. \versionadded{2.4} + +See the \UNIX{} man page \manpage{atof}{2} for details. +\end{cfuncdesc} Modified: python/branches/p3yk/Doc/commontex/copyright.tex ============================================================================== --- python/branches/p3yk/Doc/commontex/copyright.tex (original) +++ python/branches/p3yk/Doc/commontex/copyright.tex Fri Apr 27 21:54:29 2007 @@ -1,4 +1,4 @@ -Copyright \copyright{} 2001-2006 Python Software Foundation. +Copyright \copyright{} 2001-2007 Python Software Foundation. All rights reserved. Copyright \copyright{} 2000 BeOpen.com. Modified: python/branches/p3yk/Doc/commontex/license.tex ============================================================================== --- python/branches/p3yk/Doc/commontex/license.tex (original) +++ python/branches/p3yk/Doc/commontex/license.tex Fri Apr 27 21:54:29 2007 @@ -52,6 +52,7 @@ \linev{2.4.3}{2.4.2}{2006}{PSF}{yes} \linev{2.4.4}{2.4.3}{2006}{PSF}{yes} \linev{2.5}{2.4}{2006}{PSF}{yes} + \linev{2.5.1}{2.5}{2007}{PSF}{yes} \end{tablev} \note{GPL-compatible doesn't mean that we're distributing @@ -82,7 +83,7 @@ prepare derivative works, distribute, and otherwise use Python \version{} alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., -``Copyright \copyright{} 2001-2006 Python Software Foundation; All +``Copyright \copyright{} 2001-2007 Python Software Foundation; All Rights Reserved'' are retained in Python \version{} alone or in any derivative version prepared by Licensee. Modified: python/branches/p3yk/Doc/dist/dist.tex ============================================================================== --- python/branches/p3yk/Doc/dist/dist.tex (original) +++ python/branches/p3yk/Doc/dist/dist.tex Fri Apr 27 21:54:29 2007 @@ -1802,9 +1802,9 @@ setup.py foo.py \end{verbatim} -(In all diagrams in this section, \verb|| will refer to the -distribution root directory.) A minimal setup script to describe this -situation would be: +(In all diagrams in this section, \var{\textless root\textgreater} +will refer to the distribution root directory.) A minimal setup script +to describe this situation would be: \begin{verbatim} from distutils.core import setup setup(name='foo', @@ -3179,7 +3179,7 @@ Note that this is not a fully-fledged string interpolation function. A valid \code{\$variable} can consist only of upper and lower case letters, -numbers and an underscore. No \{ \} or \( \) style quoting is available. +numbers and an underscore. No \{ \} or ( ) style quoting is available. \end{funcdesc} \begin{funcdesc}{grok_environment_error}{exc\optional{, prefix=\samp{'error: '}}} @@ -3733,7 +3733,7 @@ Subclasses of \class{Command} must define the following methods. -\begin{methoddesc}{initialize_options()} +\begin{methoddesc}[Command]{initialize_options()} Set default values for all the options that this command supports. Note that these defaults may be overridden by other commands, by the setup script, by config files, or by the @@ -3742,7 +3742,7 @@ are just a bunch of \samp{self.foo = None} assignments. \end{methoddesc} -\begin{methoddesc}{finalize_options}{} +\begin{methoddesc}[Command]{finalize_options}{} Set final values for all the options that this command supports. This is always called as late as possible, ie. after any option assignments from the command-line or from other commands have been @@ -3751,7 +3751,7 @@ \var{bar} as long as \var{foo} still has the same value it was assigned in \method{initialize_options()}. \end{methoddesc} -\begin{methoddesc}{run}{} +\begin{methoddesc}[Command]{run}{} A command's raison d'etre: carry out the action it exists to perform, controlled by the options initialized in \method{initialize_options()}, customized by other commands, the setup Modified: python/branches/p3yk/Doc/ext/newtypes.tex ============================================================================== --- python/branches/p3yk/Doc/ext/newtypes.tex (original) +++ python/branches/p3yk/Doc/ext/newtypes.tex Fri Apr 27 21:54:29 2007 @@ -489,7 +489,6 @@ garbage collection, there are calls that can be made to ``untrack'' the object from garbage collection, however, these calls are advanced and not covered here.} -\item \end{itemize} @@ -930,6 +929,102 @@ collection. Most extensions will use the versions automatically provided. +\subsection{Subclassing other types} + +It is possible to create new extension types that are derived from existing +types. It is easiest to inherit from the built in types, since an extension +can easily use the \class{PyTypeObject} it needs. It can be difficult to +share these \class{PyTypeObject} structures between extension modules. + +In this example we will create a \class{Shoddy} type that inherits from +the builtin \class{list} type. The new type will be completely compatible +with regular lists, but will have an additional \method{increment()} method +that increases an internal counter. + +\begin{verbatim} +>>> import shoddy +>>> s = shoddy.Shoddy(range(3)) +>>> s.extend(s) +>>> print len(s) +6 +>>> print s.increment() +1 +>>> print s.increment() +2 +\end{verbatim} + +\verbatiminput{shoddy.c} + +As you can see, the source code closely resembles the \class{Noddy} examples in previous +sections. We will break down the main differences between them. + +\begin{verbatim} +typedef struct { + PyListObject list; + int state; +} Shoddy; +\end{verbatim} + +The primary difference for derived type objects is that the base type's +object structure must be the first value. The base type will already +include the \cfunction{PyObject_HEAD} at the beginning of its structure. + +When a Python object is a \class{Shoddy} instance, its \var{PyObject*} pointer +can be safely cast to both \var{PyListObject*} and \var{Shoddy*}. + +\begin{verbatim} +static int +Shoddy_init(Shoddy *self, PyObject *args, PyObject *kwds) +{ + if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0) + return -1; + self->state = 0; + return 0; +} +\end{verbatim} + +In the \member{__init__} method for our type, we can see how to call through +to the \member{__init__} method of the base type. + +This pattern is important when writing a type with custom \member{new} and +\member{dealloc} methods. The \member{new} method should not actually create the +memory for the object with \member{tp_alloc}, that will be handled by +the base class when calling its \member{tp_new}. + +When filling out the \cfunction{PyTypeObject} for the \class{Shoddy} type, +you see a slot for \cfunction{tp_base}. Due to cross platform compiler +issues, you can't fill that field directly with the \cfunction{PyList_Type}; +it can be done later in the module's \cfunction{init} function. + +\begin{verbatim} +PyMODINIT_FUNC +initshoddy(void) +{ + PyObject *m; + + ShoddyType.tp_base = &PyList_Type; + if (PyType_Ready(&ShoddyType) < 0) + return; + + m = Py_InitModule3("shoddy", NULL, "Shoddy module"); + if (m == NULL) + return; + + Py_INCREF(&ShoddyType); + PyModule_AddObject(m, "Shoddy", (PyObject *) &ShoddyType); +} +\end{verbatim} + +Before calling \cfunction{PyType_Ready}, the type structure must have the +\member{tp_base} slot filled in. When we are deriving a new type, it is +not necessary to fill out the \member{tp_alloc} slot with +\cfunction{PyType_GenericNew} -- the allocate function from the base type +will be inherited. + +After that, calling \cfunction{PyType_Ready} and adding the type object +to the module is the same as with the basic \class{Noddy} examples. + + \section{Type Methods \label{dnt-type-methods}} Modified: python/branches/p3yk/Doc/inst/inst.tex ============================================================================== --- python/branches/p3yk/Doc/inst/inst.tex (original) +++ python/branches/p3yk/Doc/inst/inst.tex Fri Apr 27 21:54:29 2007 @@ -296,7 +296,7 @@ \filevar{prefix} and \filevar{exec-prefix} stand for the directories that Python is installed to, and where it finds its libraries at run-time. They are always the same under Windows, and very -often the same under \UNIX and Mac OS X. You can find out what your Python +often the same under \UNIX{} and Mac OS X. You can find out what your Python installation uses for \filevar{prefix} and \filevar{exec-prefix} by running Python in interactive mode and typing a few simple commands. Under \UNIX, just type \code{python} at the shell prompt. Under Modified: python/branches/p3yk/Doc/lib/compiler.tex ============================================================================== --- python/branches/p3yk/Doc/lib/compiler.tex (original) +++ python/branches/p3yk/Doc/lib/compiler.tex Fri Apr 27 21:54:29 2007 @@ -103,8 +103,7 @@ construct. The root of the tree is \class{Module} object. The abstract syntax offers a higher level interface to parsed Python -source code. The \ulink{\module{parser}} -{http://www.python.org/doc/current/lib/module-parser.html} +source code. The \refmodule{parser} module and the compiler written in C for the Python interpreter use a concrete syntax tree. The concrete syntax is tied closely to the grammar description used for the Python parser. Instead of a single Modified: python/branches/p3yk/Doc/lib/email.tex ============================================================================== --- python/branches/p3yk/Doc/lib/email.tex (original) +++ python/branches/p3yk/Doc/lib/email.tex Fri Apr 27 21:54:29 2007 @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2006 Python Software Foundation +% Copyright (C) 2001-2007 Python Software Foundation % Author: barry at python.org (Barry Warsaw) \section{\module{email} --- @@ -239,7 +239,7 @@ The \module{email} package was originally prototyped as a separate library called -\ulink{\module{mimelib}}{http://mimelib.sf.net/}. +\ulink{\texttt{mimelib}}{http://mimelib.sf.net/}. Changes have been made so that method names are more consistent, and some methods or modules have either been added or removed. The semantics of some of the methods Modified: python/branches/p3yk/Doc/lib/emailutil.tex ============================================================================== --- python/branches/p3yk/Doc/lib/emailutil.tex (original) +++ python/branches/p3yk/Doc/lib/emailutil.tex Fri Apr 27 21:54:29 2007 @@ -56,7 +56,7 @@ \code{"Mon, 20 Nov 1995 19:12:08 -0500"}. If it succeeds in parsing the date, \function{parsedate()} returns a 9-tuple that can be passed directly to \function{time.mktime()}; otherwise \code{None} will be -returned. Note that fields 6, 7, and 8 of the result tuple are not +returned. Note that indexes 6, 7, and 8 of the result tuple are not usable. \end{funcdesc} @@ -70,7 +70,7 @@ variable for the same timezone; the latter variable follows the \POSIX{} standard while this module follows \rfc{2822}.}. If the input string has no timezone, the last element of the tuple returned is -\code{None}. Note that fields 6, 7, and 8 of the result tuple are not +\code{None}. Note that indexes 6, 7, and 8 of the result tuple are not usable. \end{funcdesc} Modified: python/branches/p3yk/Doc/lib/libamoeba.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libamoeba.tex (original) +++ python/branches/p3yk/Doc/lib/libamoeba.tex Fri Apr 27 21:54:29 2007 @@ -89,25 +89,24 @@ % The following methods are defined for capability objects. -\setindexsubitem{(capability method)} -\begin{funcdesc}{dir_list}{} +\begin{methoddesc}[capability]{dir_list}{} Returns a list of the names of the entries in an Amoeba directory. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{b_read}{offset, maxsize} +\begin{methoddesc}[capability]{b_read}{offset, maxsize} Reads (at most) \var{maxsize} bytes from a bullet file at offset \var{offset.} The data is returned as a string. EOF is reported as an empty string. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{b_size}{} +\begin{methoddesc}[capability]{b_size}{} Returns the size of a bullet file. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{dir_append}{} +\begin{methoddesc}[capability]{dir_append}{} \funcline{dir_delete}{} \funcline{dir_lookup}{} \funcline{dir_replace}{} @@ -116,17 +115,17 @@ functions, but with a path relative to the capability. (For paths beginning with a slash the capability is ignored, since this is the defined semantics for Amoeba.) -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{std_info}{} +\begin{methoddesc}[capability]{std_info}{} Returns the standard info string of the object. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{tod_gettime}{} +\begin{methoddesc}[capability]{tod_gettime}{} Returns the time (in seconds since the Epoch, in UCT, as for \POSIX) from a time server. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{tod_settime}{t} +\begin{methoddesc}[capability]{tod_settime}{t} Sets the time kept by a time server. -\end{funcdesc} +\end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libasyncore.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libasyncore.tex (original) +++ python/branches/p3yk/Doc/lib/libasyncore.tex Fri Apr 27 21:54:29 2007 @@ -46,7 +46,7 @@ \begin{funcdesc}{loop}{\optional{timeout\optional{, use_poll\optional{, map\optional{,count}}}}} Enter a polling loop that terminates after count passes or all open - channels have been closed. All arguments are optional. The \var(count) + channels have been closed. All arguments are optional. The \var{count} parameter defaults to None, resulting in the loop terminating only when all channels have been closed. The \var{timeout} argument sets the timeout parameter for the appropriate \function{select()} or Modified: python/branches/p3yk/Doc/lib/libbsddb.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libbsddb.tex (original) +++ python/branches/p3yk/Doc/lib/libbsddb.tex Fri Apr 27 21:54:29 2007 @@ -2,7 +2,6 @@ Interface to Berkeley DB library} \declaremodule{extension}{bsddb} - \platform{Unix, Windows} \modulesynopsis{Interface to Berkeley DB database library} \sectionauthor{Skip Montanaro}{skip at mojam.com} @@ -46,10 +45,10 @@ instances. \begin{funcdesc}{hashopen}{filename\optional{, flag\optional{, - mode\optional{, bsize\optional{, + mode\optional{, pgsize\optional{, ffactor\optional{, nelem\optional{, - cachesize\optional{, hash\optional{, - lorder}}}}}}}}} + cachesize\optional{, lorder\optional{, + hflags}}}}}}}}} Open the hash format file named \var{filename}. Files never intended to be preserved on disk may be created by passing \code{None} as the \var{filename}. The optional @@ -80,7 +79,7 @@ \begin{funcdesc}{rnopen}{filename\optional{, flag\optional{, mode\optional{, rnflags\optional{, cachesize\optional{, pgsize\optional{, lorder\optional{, -reclen\optional{, bval\optional{, bfname}}}}}}}}}} +rlen\optional{, delim\optional{, source\optional{, pad}}}}}}}}}}} Open a DB record format file named \var{filename}. Files never intended to be preserved on disk may be created by passing \code{None} as the @@ -114,23 +113,23 @@ the methods listed below. \versionchanged[Added dictionary methods]{2.3.1} -\begin{methoddesc}{close}{} +\begin{methoddesc}[bsddbobject]{close}{} Close the underlying file. The object can no longer be accessed. Since there is no open \method{open} method for these objects, to open the file again a new \module{bsddb} module open function must be called. \end{methoddesc} -\begin{methoddesc}{keys}{} +\begin{methoddesc}[bsddbobject]{keys}{} Return the list of keys contained in the DB file. The order of the list is unspecified and should not be relied on. In particular, the order of the list returned is different for different file formats. \end{methoddesc} -\begin{methoddesc}{has_key}{key} +\begin{methoddesc}[bsddbobject]{has_key}{key} Return \code{1} if the DB file contains the argument as a key. \end{methoddesc} -\begin{methoddesc}{set_location}{key} +\begin{methoddesc}[bsddbobject]{set_location}{key} Set the cursor to the item indicated by \var{key} and return a tuple containing the key and its value. For binary tree databases (opened using \function{btopen()}), if \var{key} does not actually exist in @@ -140,32 +139,32 @@ database. \end{methoddesc} -\begin{methoddesc}{first}{} +\begin{methoddesc}[bsddbobject]{first}{} Set the cursor to the first item in the DB file and return it. The order of keys in the file is unspecified, except in the case of B-Tree databases. This method raises \exception{bsddb.error} if the database is empty. \end{methoddesc} -\begin{methoddesc}{next}{} +\begin{methoddesc}[bsddbobject]{next}{} Set the cursor to the next item in the DB file and return it. The order of keys in the file is unspecified, except in the case of B-Tree databases. \end{methoddesc} -\begin{methoddesc}{previous}{} +\begin{methoddesc}[bsddbobject]{previous}{} Set the cursor to the previous item in the DB file and return it. The order of keys in the file is unspecified, except in the case of B-Tree databases. This is not supported on hashtable databases (those opened with \function{hashopen()}). \end{methoddesc} -\begin{methoddesc}{last}{} +\begin{methoddesc}[bsddbobject]{last}{} Set the cursor to the last item in the DB file and return it. The order of keys in the file is unspecified. This is not supported on hashtable databases (those opened with \function{hashopen()}). This method raises \exception{bsddb.error} if the database is empty. \end{methoddesc} -\begin{methoddesc}{sync}{} +\begin{methoddesc}[bsddbobject]{sync}{} Synchronize the database on disk. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libcfgparser.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcfgparser.tex (original) +++ python/branches/p3yk/Doc/lib/libcfgparser.tex Fri Apr 27 21:54:29 2007 @@ -155,37 +155,37 @@ \class{RawConfigParser} instances have the following methods: -\begin{methoddesc}{defaults}{} +\begin{methoddesc}[RawConfigParser]{defaults}{} Return a dictionary containing the instance-wide defaults. \end{methoddesc} -\begin{methoddesc}{sections}{} +\begin{methoddesc}[RawConfigParser]{sections}{} Return a list of the sections available; \code{DEFAULT} is not included in the list. \end{methoddesc} -\begin{methoddesc}{add_section}{section} +\begin{methoddesc}[RawConfigParser]{add_section}{section} Add a section named \var{section} to the instance. If a section by the given name already exists, \exception{DuplicateSectionError} is raised. \end{methoddesc} -\begin{methoddesc}{has_section}{section} +\begin{methoddesc}[RawConfigParser]{has_section}{section} Indicates whether the named section is present in the configuration. The \code{DEFAULT} section is not acknowledged. \end{methoddesc} -\begin{methoddesc}{options}{section} +\begin{methoddesc}[RawConfigParser]{options}{section} Returns a list of options available in the specified \var{section}. \end{methoddesc} -\begin{methoddesc}{has_option}{section, option} +\begin{methoddesc}[RawConfigParser]{has_option}{section, option} If the given section exists, and contains the given option, return \constant{True}; otherwise return \constant{False}. \versionadded{1.6} \end{methoddesc} -\begin{methoddesc}{read}{filenames} +\begin{methoddesc}[RawConfigParser]{read}{filenames} Attempt to read and parse a list of filenames, returning a list of filenames which were successfully parsed. If \var{filenames} is a string or Unicode string, it is treated as a single filename. @@ -210,28 +210,28 @@ \versionchanged[Returns list of successfully parsed filenames]{2.4} \end{methoddesc} -\begin{methoddesc}{readfp}{fp\optional{, filename}} +\begin{methoddesc}[RawConfigParser]{readfp}{fp\optional{, filename}} Read and parse configuration data from the file or file-like object in \var{fp} (only the \method{readline()} method is used). If \var{filename} is omitted and \var{fp} has a \member{name} attribute, that is used for \var{filename}; the default is \samp{}. \end{methoddesc} -\begin{methoddesc}{get}{section, option} +\begin{methoddesc}[RawConfigParser]{get}{section, option} Get an \var{option} value for the named \var{section}. \end{methoddesc} -\begin{methoddesc}{getint}{section, option} +\begin{methoddesc}[RawConfigParser]{getint}{section, option} A convenience method which coerces the \var{option} in the specified \var{section} to an integer. \end{methoddesc} -\begin{methoddesc}{getfloat}{section, option} +\begin{methoddesc}[RawConfigParser]{getfloat}{section, option} A convenience method which coerces the \var{option} in the specified \var{section} to a floating point number. \end{methoddesc} -\begin{methoddesc}{getboolean}{section, option} +\begin{methoddesc}[RawConfigParser]{getboolean}{section, option} A convenience method which coerces the \var{option} in the specified \var{section} to a Boolean value. Note that the accepted values for the option are \code{"1"}, \code{"yes"}, \code{"true"}, and \code{"on"}, @@ -241,12 +241,12 @@ cause it to raise \exception{ValueError}. \end{methoddesc} -\begin{methoddesc}{items}{section} +\begin{methoddesc}[RawConfigParser]{items}{section} Return a list of \code{(\var{name}, \var{value})} pairs for each option in the given \var{section}. \end{methoddesc} -\begin{methoddesc}{set}{section, option, value} +\begin{methoddesc}[RawConfigParser]{set}{section, option, value} If the given section exists, set the given option to the specified value; otherwise raise \exception{NoSectionError}. While it is possible to use \class{RawConfigParser} (or \class{ConfigParser} with @@ -256,14 +256,14 @@ \versionadded{1.6} \end{methoddesc} -\begin{methoddesc}{write}{fileobject} +\begin{methoddesc}[RawConfigParser]{write}{fileobject} Write a representation of the configuration to the specified file object. This representation can be parsed by a future \method{read()} call. \versionadded{1.6} \end{methoddesc} -\begin{methoddesc}{remove_option}{section, option} +\begin{methoddesc}[RawConfigParser]{remove_option}{section, option} Remove the specified \var{option} from the specified \var{section}. If the section does not exist, raise \exception{NoSectionError}. If the option existed to be removed, return \constant{True}; @@ -271,13 +271,13 @@ \versionadded{1.6} \end{methoddesc} -\begin{methoddesc}{remove_section}{section} +\begin{methoddesc}[RawConfigParser]{remove_section}{section} Remove the specified \var{section} from the configuration. If the section in fact existed, return \code{True}. Otherwise return \code{False}. \end{methoddesc} -\begin{methoddesc}{optionxform}{option} +\begin{methoddesc}[RawConfigParser]{optionxform}{option} Transforms the option name \var{option} as found in an input file or as passed in by client code to the form that should be used in the internal structures. The default implementation returns a lower-case @@ -293,14 +293,14 @@ The \class{ConfigParser} class extends some methods of the \class{RawConfigParser} interface, adding some optional arguments. -\begin{methoddesc}{get}{section, option\optional{, raw\optional{, vars}}} +\begin{methoddesc}[ConfigParser]{get}{section, option\optional{, raw\optional{, vars}}} Get an \var{option} value for the named \var{section}. All the \character{\%} interpolations are expanded in the return values, based on the defaults passed into the constructor, as well as the options \var{vars} provided, unless the \var{raw} argument is true. \end{methoddesc} -\begin{methoddesc}{items}{section\optional{, raw\optional{, vars}}} +\begin{methoddesc}[ConfigParser]{items}{section\optional{, raw\optional{, vars}}} Return a list of \code{(\var{name}, \var{value})} pairs for each option in the given \var{section}. Optional arguments have the same meaning as for the \method{get()} method. @@ -313,7 +313,7 @@ The \class{SafeConfigParser} class implements the same extended interface as \class{ConfigParser}, with the following addition: -\begin{methoddesc}{set}{section, option, value} +\begin{methoddesc}[SafeConfigParser]{set}{section, option, value} If the given section exists, set the given option to the specified value; otherwise raise \exception{NoSectionError}. \var{value} must be a string (\class{str} or \class{unicode}); if not, Modified: python/branches/p3yk/Doc/lib/libcgitb.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcgitb.tex (original) +++ python/branches/p3yk/Doc/lib/libcgitb.tex Fri Apr 27 21:54:29 2007 @@ -38,7 +38,7 @@ context\optional{, format}}}}} This function causes the \module{cgitb} module to take over the interpreter's default handling for exceptions by setting the - value of \code{\refmodule{sys}.excepthook}. + value of \member{\refmodule{sys}.excepthook}. \withsubitem{(in module sys)}{\ttindex{excepthook()}} The optional argument \var{display} defaults to \code{1} and can be set @@ -61,7 +61,7 @@ report it using \module{cgitb}. The optional \var{info} argument should be a 3-tuple containing an exception type, exception value, and traceback object, exactly like the tuple returned by - \code{\refmodule{sys}.exc_info()}. If the \var{info} argument + \function{\refmodule{sys}.exc_info()}. If the \var{info} argument is not supplied, the current exception is obtained from - \code{\refmodule{sys}.exc_info()}. + \function{\refmodule{sys}.exc_info()}. \end{funcdesc} Modified: python/branches/p3yk/Doc/lib/libcmath.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcmath.tex (original) +++ python/branches/p3yk/Doc/lib/libcmath.tex Fri Apr 27 21:54:29 2007 @@ -5,7 +5,14 @@ \modulesynopsis{Mathematical functions for complex numbers.} This module is always available. It provides access to mathematical -functions for complex numbers. The functions are: +functions for complex numbers. The functions in this module accept +integers, floating-point numbers or complex numbers as arguments. +They will also accept any Python object that has either a +\method{__complex__} or a \method{__float__} method: these methods are +used to convert the object to a complex or floating-point number, respectively, and +the function is then applied to the result of the conversion. + +The functions are: \begin{funcdesc}{acos}{x} Return the arc cosine of \var{x}. Modified: python/branches/p3yk/Doc/lib/libcmd.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcmd.tex (original) +++ python/branches/p3yk/Doc/lib/libcmd.tex Fri Apr 27 21:54:29 2007 @@ -37,7 +37,7 @@ A \class{Cmd} instance has the following methods: -\begin{methoddesc}{cmdloop}{\optional{intro}} +\begin{methoddesc}[Cmd]{cmdloop}{\optional{intro}} Repeatedly issue a prompt, accept input, parse an initial prefix off the received input, and dispatch to action methods, passing them the remainder of the line as argument. @@ -82,7 +82,7 @@ any undocumented commands. \end{methoddesc} -\begin{methoddesc}{onecmd}{str} +\begin{methoddesc}[Cmd]{onecmd}{str} Interpret the argument as though it had been typed in response to the prompt. This may be overridden, but should not normally need to be; see the \method{precmd()} and \method{postcmd()} methods for useful @@ -93,25 +93,25 @@ \method{default()} method is returned. \end{methoddesc} -\begin{methoddesc}{emptyline}{} +\begin{methoddesc}[Cmd]{emptyline}{} Method called when an empty line is entered in response to the prompt. If this method is not overridden, it repeats the last nonempty command entered. \end{methoddesc} -\begin{methoddesc}{default}{line} +\begin{methoddesc}[Cmd]{default}{line} Method called on an input line when the command prefix is not recognized. If this method is not overridden, it prints an error message and returns. \end{methoddesc} -\begin{methoddesc}{completedefault}{text, line, begidx, endidx} +\begin{methoddesc}[Cmd]{completedefault}{text, line, begidx, endidx} Method called to complete an input line when no command-specific \method{complete_*()} method is available. By default, it returns an empty list. \end{methoddesc} -\begin{methoddesc}{precmd}{line} +\begin{methoddesc}[Cmd]{precmd}{line} Hook method executed just before the command line \var{line} is interpreted, but after the input prompt is generated and issued. This method is a stub in \class{Cmd}; it exists to be overridden by @@ -121,7 +121,7 @@ unchanged. \end{methoddesc} -\begin{methoddesc}{postcmd}{stop, line} +\begin{methoddesc}[Cmd]{postcmd}{stop, line} Hook method executed just after a command dispatch is finished. This method is a stub in \class{Cmd}; it exists to be overridden by subclasses. \var{line} is the command line which was executed, and @@ -133,13 +133,13 @@ to continue. \end{methoddesc} -\begin{methoddesc}{preloop}{} +\begin{methoddesc}[Cmd]{preloop}{} Hook method executed once when \method{cmdloop()} is called. This method is a stub in \class{Cmd}; it exists to be overridden by subclasses. \end{methoddesc} -\begin{methoddesc}{postloop}{} +\begin{methoddesc}[Cmd]{postloop}{} Hook method executed once when \method{cmdloop()} is about to return. This method is a stub in \class{Cmd}; it exists to be overridden by subclasses. @@ -147,42 +147,52 @@ Instances of \class{Cmd} subclasses have some public instance variables: -\begin{memberdesc}{prompt} +\begin{memberdesc}[Cmd]{prompt} The prompt issued to solicit input. \end{memberdesc} -\begin{memberdesc}{identchars} +\begin{memberdesc}[Cmd]{identchars} The string of characters accepted for the command prefix. \end{memberdesc} -\begin{memberdesc}{lastcmd} +\begin{memberdesc}[Cmd]{lastcmd} The last nonempty command prefix seen. \end{memberdesc} -\begin{memberdesc}{intro} +\begin{memberdesc}[Cmd]{intro} A string to issue as an intro or banner. May be overridden by giving the \method{cmdloop()} method an argument. \end{memberdesc} -\begin{memberdesc}{doc_header} +\begin{memberdesc}[Cmd]{doc_header} The header to issue if the help output has a section for documented commands. \end{memberdesc} -\begin{memberdesc}{misc_header} +\begin{memberdesc}[Cmd]{misc_header} The header to issue if the help output has a section for miscellaneous help topics (that is, there are \method{help_*()} methods without corresponding \method{do_*()} methods). \end{memberdesc} -\begin{memberdesc}{undoc_header} +\begin{memberdesc}[Cmd]{undoc_header} The header to issue if the help output has a section for undocumented commands (that is, there are \method{do_*()} methods without corresponding \method{help_*()} methods). \end{memberdesc} -\begin{memberdesc}{ruler} +\begin{memberdesc}[Cmd]{ruler} The character used to draw separator lines under the help-message headers. If empty, no ruler line is drawn. It defaults to \character{=}. \end{memberdesc} + +\begin{memberdesc}[Cmd]{use_rawinput} +A flag, defaulting to true. If true, \method{cmdloop()} uses +\function{input()} to display a prompt and read the next command; +if false, \method{sys.stdout.write()} and +\method{sys.stdin.readline()} are used. (This means that by +importing \refmodule{readline}, on systems that support it, the +interpreter will automatically support \program{Emacs}-like line editing +and command-history keystrokes.) +\end{memberdesc} Modified: python/branches/p3yk/Doc/lib/libcode.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcode.tex (original) +++ python/branches/p3yk/Doc/lib/libcode.tex Fri Apr 27 21:54:29 2007 @@ -68,7 +68,7 @@ \subsection{Interactive Interpreter Objects \label{interpreter-objects}} -\begin{methoddesc}{runsource}{source\optional{, filename\optional{, symbol}}} +\begin{methoddesc}[InteractiveInterpreter]{runsource}{source\optional{, filename\optional{, symbol}}} Compile and run some source in the interpreter. Arguments are the same as for \function{compile_command()}; the default for \var{filename} is \code{''}, and for @@ -98,7 +98,7 @@ \code{sys.ps1} or \code{sys.ps2} to prompt the next line. \end{methoddesc} -\begin{methoddesc}{runcode}{code} +\begin{methoddesc}[InteractiveInterpreter]{runcode}{code} Execute a code object. When an exception occurs, \method{showtraceback()} is called to display a traceback. All exceptions are caught except @@ -109,7 +109,7 @@ should be prepared to deal with it. \end{methoddesc} -\begin{methoddesc}{showsyntaxerror}{\optional{filename}} +\begin{methoddesc}[InteractiveInterpreter]{showsyntaxerror}{\optional{filename}} Display the syntax error that just occurred. This does not display a stack trace because there isn't one for syntax errors. If \var{filename} is given, it is stuffed into the exception instead @@ -118,13 +118,13 @@ The output is written by the \method{write()} method. \end{methoddesc} -\begin{methoddesc}{showtraceback}{} +\begin{methoddesc}[InteractiveInterpreter]{showtraceback}{} Display the exception that just occurred. We remove the first stack item because it is within the interpreter object implementation. The output is written by the \method{write()} method. \end{methoddesc} -\begin{methoddesc}{write}{data} +\begin{methoddesc}[InteractiveInterpreter]{write}{data} Write a string to the standard error stream (\code{sys.stderr}). Derived classes should override this to provide the appropriate output handling as needed. @@ -138,7 +138,7 @@ \class{InteractiveInterpreter}, and so offers all the methods of the interpreter objects as well as the following additions. -\begin{methoddesc}{interact}{\optional{banner}} +\begin{methoddesc}[InteractiveConsole]{interact}{\optional{banner}} Closely emulate the interactive Python console. The optional banner argument specify the banner to print before the first interaction; by default it prints a banner similar to the one @@ -147,7 +147,7 @@ with the real interpreter -- since it's so close!). \end{methoddesc} -\begin{methoddesc}{push}{line} +\begin{methoddesc}[InteractiveConsole]{push}{line} Push a line of source text to the interpreter. The line should not have a trailing newline; it may have internal newlines. The line is appended to a buffer and the interpreter's @@ -160,11 +160,11 @@ \method{runsource()}). \end{methoddesc} -\begin{methoddesc}{resetbuffer}{} +\begin{methoddesc}[InteractiveConsole]{resetbuffer}{} Remove any unhandled source text from the input buffer. \end{methoddesc} -\begin{methoddesc}{raw_input}{\optional{prompt}} +\begin{methoddesc}[InteractiveConsole]{raw_input}{\optional{prompt}} Write a prompt and read a line. The returned line does not include the trailing newline. When the user enters the \EOF{} key sequence, \exception{EOFError} is raised. The base implementation reads from Modified: python/branches/p3yk/Doc/lib/libcodecs.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcodecs.tex (original) +++ python/branches/p3yk/Doc/lib/libcodecs.tex Fri Apr 27 21:54:29 2007 @@ -307,7 +307,7 @@ The \class{Codec} class defines these methods which also define the function interfaces of the stateless encoder and decoder: -\begin{methoddesc}{encode}{input\optional{, errors}} +\begin{methoddesc}[Codec]{encode}{input\optional{, errors}} Encodes the object \var{input} and returns a tuple (output object, length consumed). While codecs are not restricted to use with Unicode, in a Unicode context, encoding converts a Unicode object to a plain string @@ -325,7 +325,7 @@ empty object of the output object type in this situation. \end{methoddesc} -\begin{methoddesc}{decode}{input\optional{, errors}} +\begin{methoddesc}[Codec]{decode}{input\optional{, errors}} Decodes the object \var{input} and returns a tuple (output object, length consumed). In a Unicode context, decoding converts a plain string encoded using a particular character set encoding to a Unicode object. @@ -1233,9 +1233,8 @@ \lineiv{idna} {} {Unicode string} - {Implements \rfc{3490}. - \versionadded{2.3} - See also \refmodule{encodings.idna}} + {Implements \rfc{3490}, + see also \refmodule{encodings.idna}} \lineiv{mbcs} {dbcs} @@ -1250,8 +1249,7 @@ \lineiv{punycode} {} {Unicode string} - {Implements \rfc{3492}. - \versionadded{2.3}} + {Implements \rfc{3492}} \lineiv{quopri_codec} {quopri, quoted-printable, quotedprintable} @@ -1305,6 +1303,8 @@ \end{tableiv} +\versionadded[The \code{idna} and \code{punycode} encodings]{2.3} + \subsection{\module{encodings.idna} --- Internationalized Domain Names in Applications} Modified: python/branches/p3yk/Doc/lib/libcollections.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcollections.tex (original) +++ python/branches/p3yk/Doc/lib/libcollections.tex Fri Apr 27 21:54:29 2007 @@ -9,14 +9,16 @@ This module implements high-performance container datatypes. Currently, -there are two datatypes, deque and defaultdict. +there are two datatypes, deque and defaultdict, and one datatype factory +function, \function{NamedTuple}. Future additions may include balanced trees and ordered dictionaries. \versionchanged[Added defaultdict]{2.5} +\versionchanged[Added NamedTuple]{2.6} \subsection{\class{deque} objects \label{deque-objects}} -\begin{funcdesc}{deque}{\optional{iterable}} - Returns a new deque objected initialized left-to-right (using +\begin{classdesc}{deque}{\optional{iterable}} + Returns a new deque object initialized left-to-right (using \method{append()}) with data from \var{iterable}. If \var{iterable} is not specified, the new deque is empty. @@ -30,7 +32,7 @@ for \samp{pop(0)} and \samp{insert(0, v)} operations which change both the size and position of the underlying data representation. \versionadded{2.4} -\end{funcdesc} +\end{classdesc} Deque objects support the following methods: @@ -219,7 +221,7 @@ \subsection{\class{defaultdict} objects \label{defaultdict-objects}} -\begin{funcdesc}{defaultdict}{\optional{default_factory\optional{, ...}}} +\begin{classdesc}{defaultdict}{\optional{default_factory\optional{, ...}}} Returns a new dictionary-like object. \class{defaultdict} is a subclass of the builtin \class{dict} class. It overrides one method and adds one writable instance variable. The remaining functionality is the same as @@ -231,7 +233,7 @@ passed to the \class{dict} constructor, including keyword arguments. \versionadded{2.5} -\end{funcdesc} +\end{classdesc} \class{defaultdict} objects support the following method in addition to the standard \class{dict} operations: @@ -254,11 +256,11 @@ \class{defaultdict} objects support the following instance variable: -\begin{datadesc}{default_factory} +\begin{memberdesc}{default_factory} This attribute is used by the \method{__missing__} method; it is initialized from the first argument to the constructor, if present, or to \code{None}, if absent. -\end{datadesc} +\end{memberdesc} \subsubsection{\class{defaultdict} Examples \label{defaultdict-examples}} @@ -339,3 +341,51 @@ >>> d.items() [('blue', set([2, 4])), ('red', set([1, 3]))] \end{verbatim} + + + +\subsection{\function{NamedTuple} datatype factory function \label{named-tuple-factory}} + +\begin{funcdesc}{NamedTuple}{typename, fieldnames} + Returns a new tuple subclass named \var{typename}. The new subclass is used + to create tuple-like objects that have fields accessable by attribute + lookup as well as being indexable and iterable. Instances of the subclass + also have a helpful docstring (with typename and fieldnames) and a helpful + \method{__repr__()} method which lists the tuple contents in a \code{name=value} + format. + \versionadded{2.6} + + The \var{fieldnames} are specified in a single string and are separated by spaces. + Any valid Python identifier may be used for a field name. + + Example: + \begin{verbatim} +>>> Point = NamedTuple('Point', 'x y') +>>> Point.__doc__ # docstring for the new datatype +'Point(x, y)' +>>> p = Point(11, y=22) # instantiate with positional or keyword arguments +>>> p[0] + p[1] # works just like the tuple (11, 22) +33 +>>> x, y = p # unpacks just like a tuple +>>> x, y +(11, 22) +>>> p.x + p.y # fields also accessable by name +33 +>>> p # readable __repr__ with name=value style +Point(x=11, y=22) +\end{verbatim} + + The use cases are the same as those for tuples. The named factories + assign meaning to each tuple position and allow for more readable, + self-documenting code. Named tuples can also be used to assign field names + to tuples + returned by the \module{csv} or \module{sqlite3} modules. For example: + + \begin{verbatim} +import csv +EmployeeRecord = NamedTuple('EmployeeRecord', 'name age title department paygrade') +for tup in csv.reader(open("employees.csv", "rb")): + print EmployeeRecord(*tup) +\end{verbatim} + +\end{funcdesc} Modified: python/branches/p3yk/Doc/lib/libcommands.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcommands.tex (original) +++ python/branches/p3yk/Doc/lib/libcommands.tex Fri Apr 27 21:54:29 2007 @@ -39,6 +39,10 @@ Return the output of \samp{ls -ld \var{file}} as a string. This function uses the \function{getoutput()} function, and properly escapes backslashes and dollar signs in the argument. + +\deprecated{2.6}{This function is nonobvious and useless, + also the name is misleading in the presence of + \function{getstatusoutput()}.} \end{funcdesc} Example: Modified: python/branches/p3yk/Doc/lib/libconsts.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libconsts.tex (original) +++ python/branches/p3yk/Doc/lib/libconsts.tex Fri Apr 27 21:54:29 2007 @@ -13,7 +13,7 @@ \end{datadesc} \begin{datadesc}{None} - The sole value of \code{\refmodule{types}.NoneType}. \code{None} is + The sole value of \member{\refmodule{types}.NoneType}. \code{None} is frequently used to represent the absence of a value, as when default arguments are not passed to a function. \end{datadesc} Modified: python/branches/p3yk/Doc/lib/libcookielib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcookielib.tex (original) +++ python/branches/p3yk/Doc/lib/libcookielib.tex Fri Apr 27 21:54:29 2007 @@ -292,12 +292,12 @@ \class{FileCookieJar} instances have the following public attributes: -\begin{memberdesc}{filename} +\begin{memberdesc}[FileCookieJar]{filename} Filename of default file in which to keep cookies. This attribute may be assigned to. \end{memberdesc} -\begin{memberdesc}{delayload} +\begin{memberdesc}[FileCookieJar]{delayload} If true, load cookies lazily from disk. This attribute should not be assigned to. This is only a hint, since this only affects performance, not behaviour (unless the cookies on disk are changing). @@ -400,13 +400,13 @@ attributes, indicating which protocols should be used, and how. All of these attributes may be assigned to. -\begin{memberdesc}{netscape} +\begin{memberdesc}[CookiePolicy]{netscape} Implement Netscape protocol. \end{memberdesc} -\begin{memberdesc}{rfc2965} +\begin{memberdesc}[CookiePolicy]{rfc2965} Implement RFC 2965 protocol. \end{memberdesc} -\begin{memberdesc}{hide_cookie2} +\begin{memberdesc}[CookiePolicy]{hide_cookie2} Don't add \mailheader{Cookie2} header to requests (the presence of this header indicates to the server that we understand RFC 2965 cookies). @@ -504,7 +504,7 @@ which are all initialised from the constructor arguments of the same name, and which may all be assigned to. -\begin{memberdesc}{rfc2109_as_netscape} +\begin{memberdesc}[DefaultCookiePolicy]{rfc2109_as_netscape} If true, request that the \class{CookieJar} instance downgrade RFC 2109 cookies (ie. cookies received in a \mailheader{Set-Cookie} header with a version cookie-attribute of 1) to Netscape cookies by setting @@ -517,7 +517,7 @@ General strictness switches: -\begin{memberdesc}{strict_domain} +\begin{memberdesc}[DefaultCookiePolicy]{strict_domain} Don't allow sites to set two-component domains with country-code top-level domains like \code{.co.uk}, \code{.gov.uk}, \code{.co.nz}.etc. This is far from perfect and isn't guaranteed to @@ -526,7 +526,7 @@ RFC 2965 protocol strictness switches: -\begin{memberdesc}{strict_rfc2965_unverifiable} +\begin{memberdesc}[DefaultCookiePolicy]{strict_rfc2965_unverifiable} Follow RFC 2965 rules on unverifiable transactions (usually, an unverifiable transaction is one resulting from a redirect or a request for an image hosted on another site). If this is false, cookies are @@ -535,19 +535,19 @@ Netscape protocol strictness switches: -\begin{memberdesc}{strict_ns_unverifiable} +\begin{memberdesc}[DefaultCookiePolicy]{strict_ns_unverifiable} apply RFC 2965 rules on unverifiable transactions even to Netscape cookies \end{memberdesc} -\begin{memberdesc}{strict_ns_domain} +\begin{memberdesc}[DefaultCookiePolicy]{strict_ns_domain} Flags indicating how strict to be with domain-matching rules for Netscape cookies. See below for acceptable values. \end{memberdesc} -\begin{memberdesc}{strict_ns_set_initial_dollar} +\begin{memberdesc}[DefaultCookiePolicy]{strict_ns_set_initial_dollar} Ignore cookies in Set-Cookie: headers that have names starting with \code{'\$'}. \end{memberdesc} -\begin{memberdesc}{strict_ns_set_path} +\begin{memberdesc}[DefaultCookiePolicy]{strict_ns_set_path} Don't allow setting cookies whose path doesn't path-match request URI. \end{memberdesc} @@ -556,30 +556,30 @@ \code{DomainStrictNoDots|DomainStrictNonDomain} means both flags are set). -\begin{memberdesc}{DomainStrictNoDots} +\begin{memberdesc}[DefaultCookiePolicy]{DomainStrictNoDots} When setting cookies, the 'host prefix' must not contain a dot (eg. \code{www.foo.bar.com} can't set a cookie for \code{.bar.com}, because \code{www.foo} contains a dot). \end{memberdesc} -\begin{memberdesc}{DomainStrictNonDomain} +\begin{memberdesc}[DefaultCookiePolicy]{DomainStrictNonDomain} Cookies that did not explicitly specify a \code{domain} cookie-attribute can only be returned to a domain equal to the domain that set the cookie (eg. \code{spam.example.com} won't be returned cookies from \code{example.com} that had no \code{domain} cookie-attribute). \end{memberdesc} -\begin{memberdesc}{DomainRFC2965Match} +\begin{memberdesc}[DefaultCookiePolicy]{DomainRFC2965Match} When setting cookies, require a full RFC 2965 domain-match. \end{memberdesc} The following attributes are provided for convenience, and are the most useful combinations of the above flags: -\begin{memberdesc}{DomainLiberal} +\begin{memberdesc}[DefaultCookiePolicy]{DomainLiberal} Equivalent to 0 (ie. all of the above Netscape domain strictness flags switched off). \end{memberdesc} -\begin{memberdesc}{DomainStrict} +\begin{memberdesc}[DefaultCookiePolicy]{DomainStrict} Equivalent to \code{DomainStrictNoDots|DomainStrictNonDomain}. \end{memberdesc} Modified: python/branches/p3yk/Doc/lib/libctypes.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libctypes.tex (original) +++ python/branches/p3yk/Doc/lib/libctypes.tex Fri Apr 27 21:54:29 2007 @@ -7,21 +7,21 @@ \versionadded{2.5} \code{ctypes} is a foreign function library for Python. It provides C -compatible data types, and allows to call functions in dlls/shared +compatible data types, and allows calling functions in dlls/shared libraries. It can be used to wrap these libraries in pure Python. \subsection{ctypes tutorial\label{ctypes-ctypes-tutorial}} -Note: The code samples in this tutorial uses \code{doctest} to make sure +Note: The code samples in this tutorial use \code{doctest} to make sure that they actually work. Since some code samples behave differently under Linux, Windows, or Mac OS X, they contain doctest directives in comments. -Note: Quite some code samples references the ctypes \class{c{\_}int} type. +Note: Some code sample references the ctypes \class{c{\_}int} type. This type is an alias to the \class{c{\_}long} type on 32-bit systems. So, you should not be confused if \class{c{\_}long} is printed if you would -expect \class{c{\_}int} - they are actually the same type. +expect \class{c{\_}int} --- they are actually the same type. \subsubsection{Loading dynamic link libraries\label{ctypes-loading-dynamic-link-libraries}} @@ -38,7 +38,7 @@ automatically raise \class{WindowsError} Python exceptions when the function call fails. -Here are some examples for Windows, note that \code{msvcrt} is the MS +Here are some examples for Windows. Note that \code{msvcrt} is the MS standard C library containing most standard C functions, and uses the cdecl calling convention: \begin{verbatim} @@ -1219,7 +1219,7 @@ It is quite interesting to see that the Windows \function{qsort} function needs more comparisons than the linux version! -As we can easily check, our array sorted now: +As we can easily check, our array is sorted now: \begin{verbatim} >>> for i in ia: print i, ... @@ -1242,7 +1242,7 @@ \programopt{-O} or \programopt{-OO} flag given on startup. \code{ctypes} can access values like this with the \method{in{\_}dll} class -methods of the type. \var{pythonapi} ?s a predefined symbol giving +methods of the type. \var{pythonapi} is a predefined symbol giving access to the Python C api: \begin{verbatim} >>> opt_flag = c_int.in_dll(pythonapi, "Py_OptimizeFlag") @@ -2113,7 +2113,7 @@ \end{memberdesc} -\subsubsection{Fundamental data types\label{ctypes-fundamental-data-types}} +\subsubsection{Fundamental data types\label{ctypes-fundamental-data-types-2}} \begin{classdesc*}{_SimpleCData} This non-public class is the base class of all fundamental ctypes @@ -2294,6 +2294,13 @@ an integer address, or a string. \end{classdesc*} +\begin{classdesc*}{c_bool} +Represent the C \code{bool} datatype (more accurately, _Bool from C99). +Its value can be True or False, and the constructor accepts any object that +has a truth value. +\versionadded{2.6} +\end{classdesc*} + \begin{classdesc*}{HRESULT} Windows only: Represents a \class{HRESULT} value, which contains success or error information for a function or method call. Modified: python/branches/p3yk/Doc/lib/libcurses.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcurses.tex (original) +++ python/branches/p3yk/Doc/lib/libcurses.tex Fri Apr 27 21:54:29 2007 @@ -646,6 +646,16 @@ corner characters are always used by this function. \end{methoddesc} +\begin{methoddesc}[window]{chgat}{\optional{y, x, } \optional{num,} attr} +Sets the attributes of \var{num} characters at the current cursor +position, or at position \code{(\var{y}, \var{x})} if supplied. If no +value of \var{num} is given or \var{num} = -1, the attribute will +be set on all the characters to the end of the line. +This function does not move the cursor. The changed line +will be touched using the \method{touchline} method so that the +contents will be redisplayed by the next window refresh. +\end{methoddesc} + \begin{methoddesc}[window]{clear}{} Like \method{erase()}, but also causes the whole window to be repainted upon next call to \method{refresh()}. @@ -1014,9 +1024,11 @@ input at the end of that time. \end{methoddesc} -\begin{methoddesc}[window]{touchline}{start, count} +\begin{methoddesc}[window]{touchline}{start, count\optional{, changed}} Pretend \var{count} lines have been changed, starting with line -\var{start}. +\var{start}. If \var{changed} is supplied, it specifies +whether the affected lines are marked as +having been changed (\var{changed}=1) or unchanged (\var{changed}=0). \end{methoddesc} \begin{methoddesc}[window]{touchwin}{} Modified: python/branches/p3yk/Doc/lib/libcursespanel.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libcursespanel.tex (original) +++ python/branches/p3yk/Doc/lib/libcursespanel.tex Fri Apr 27 21:54:29 2007 @@ -45,52 +45,52 @@ Panel objects have the following methods: -\begin{methoddesc}{above}{} +\begin{methoddesc}[Panel]{above}{} Returns the panel above the current panel. \end{methoddesc} -\begin{methoddesc}{below}{} +\begin{methoddesc}[Panel]{below}{} Returns the panel below the current panel. \end{methoddesc} -\begin{methoddesc}{bottom}{} +\begin{methoddesc}[Panel]{bottom}{} Push the panel to the bottom of the stack. \end{methoddesc} -\begin{methoddesc}{hidden}{} +\begin{methoddesc}[Panel]{hidden}{} Returns true if the panel is hidden (not visible), false otherwise. \end{methoddesc} -\begin{methoddesc}{hide}{} +\begin{methoddesc}[Panel]{hide}{} Hide the panel. This does not delete the object, it just makes the window on screen invisible. \end{methoddesc} -\begin{methoddesc}{move}{y, x} +\begin{methoddesc}[Panel]{move}{y, x} Move the panel to the screen coordinates \code{(\var{y}, \var{x})}. \end{methoddesc} -\begin{methoddesc}{replace}{win} +\begin{methoddesc}[Panel]{replace}{win} Change the window associated with the panel to the window \var{win}. \end{methoddesc} -\begin{methoddesc}{set_userptr}{obj} +\begin{methoddesc}[Panel]{set_userptr}{obj} Set the panel's user pointer to \var{obj}. This is used to associate an arbitrary piece of data with the panel, and can be any Python object. \end{methoddesc} -\begin{methoddesc}{show}{} +\begin{methoddesc}[Panel]{show}{} Display the panel (which might have been hidden). \end{methoddesc} -\begin{methoddesc}{top}{} +\begin{methoddesc}[Panel]{top}{} Push panel to the top of the stack. \end{methoddesc} -\begin{methoddesc}{userptr}{} +\begin{methoddesc}[Panel]{userptr}{} Returns the user pointer for the panel. This might be any Python object. \end{methoddesc} -\begin{methoddesc}{window}{} +\begin{methoddesc}[Panel]{window}{} Returns the window object associated with the panel. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libdatetime.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libdatetime.tex (original) +++ python/branches/p3yk/Doc/lib/libdatetime.tex Fri Apr 27 21:54:29 2007 @@ -1154,7 +1154,7 @@ uses made of aware \module{datetime} objects. If in doubt, simply implement all of them. -\begin{methoddesc}{utcoffset}{self, dt} +\begin{methoddesc}[tzinfo]{utcoffset}{self, dt} Return offset of local time from UTC, in minutes east of UTC. If local time is west of UTC, this should be negative. Note that this is intended to be the total offset from UTC; for example, if a @@ -1178,7 +1178,7 @@ \exception{NotImplementedError}. \end{methoddesc} -\begin{methoddesc}{dst}{self, dt} +\begin{methoddesc}[tzinfo]{dst}{self, dt} Return the daylight saving time (DST) adjustment, in minutes east of UTC, or \code{None} if DST information isn't known. Return \code{timedelta(0)} if DST is not in effect. @@ -1237,7 +1237,7 @@ \exception{NotImplementedError}. \end{methoddesc} -\begin{methoddesc}{tzname}{self, dt} +\begin{methoddesc}[tzinfo]{tzname}{self, dt} Return the time zone name corresponding to the \class{datetime} object \var{dt}, as a string. Nothing about string names is defined by the @@ -1278,7 +1278,7 @@ There is one more \class{tzinfo} method that a subclass may wish to override: -\begin{methoddesc}{fromutc}{self, dt} +\begin{methoddesc}[tzinfo]{fromutc}{self, dt} This is called from the default \class{datetime.astimezone()} implementation. When called from that, \code{\var{dt}.tzinfo} is \var{self}, and \var{dt}'s date and time members are to be viewed as Modified: python/branches/p3yk/Doc/lib/libdbhash.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libdbhash.tex (original) +++ python/branches/p3yk/Doc/lib/libdbhash.tex Fri Apr 27 21:54:29 2007 @@ -2,7 +2,6 @@ DBM-style interface to the BSD database library} \declaremodule{standard}{dbhash} - \platform{Unix, Windows} \modulesynopsis{DBM-style interface to the BSD database library.} \sectionauthor{Fred L. Drake, Jr.}{fdrake at acm.org} Modified: python/branches/p3yk/Doc/lib/libdecimal.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libdecimal.tex (original) +++ python/branches/p3yk/Doc/lib/libdecimal.tex Fri Apr 27 21:54:29 2007 @@ -425,7 +425,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\subsection{Context objects \label{decimal-decimal}} +\subsection{Context objects \label{decimal-context}} Contexts are environments for arithmetic operations. They govern precision, set rules for rounding, determine which signals are treated as exceptions, and Modified: python/branches/p3yk/Doc/lib/libdl.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libdl.tex (original) +++ python/branches/p3yk/Doc/lib/libdl.tex Fri Apr 27 21:54:29 2007 @@ -67,11 +67,11 @@ Dl objects, as returned by \function{open()} above, have the following methods: -\begin{methoddesc}{close}{} +\begin{methoddesc}[dl]{close}{} Free all resources, except the memory. \end{methoddesc} -\begin{methoddesc}{sym}{name} +\begin{methoddesc}[dl]{sym}{name} Return the pointer for the function named \var{name}, as a number, if it exists in the referenced shared object, otherwise \code{None}. This is useful in code like: @@ -87,7 +87,7 @@ \NULL{} pointer) \end{methoddesc} -\begin{methoddesc}{call}{name\optional{, arg1\optional{, arg2\ldots}}} +\begin{methoddesc}[dl]{call}{name\optional{, arg1\optional{, arg2\ldots}}} Call the function named \var{name} in the referenced shared object. The arguments must be either Python integers, which will be passed as is, Python strings, to which a pointer will be passed, Modified: python/branches/p3yk/Doc/lib/libdoctest.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libdoctest.tex (original) +++ python/branches/p3yk/Doc/lib/libdoctest.tex Fri Apr 27 21:54:29 2007 @@ -201,6 +201,19 @@ \code{sys.argv} is not examined by \function{testmod()} (so passing \programopt{-v} or not has no effect). +Since Python 2.6, there is also a command line shortcut for running +\function{testmod()}. You can instruct the Python interpreter to run +the doctest module directly from the standard library and pass the module +name(s) on the command line: + +\begin{verbatim} +python -m doctest -v example.py +\end{verbatim} + +This will import \file{example.py} as a standalone module and run +\function{testmod()} on it. Note that this may not work correctly if the +file is part of a package and imports other submodules from that package. + For more information on \function{testmod()}, see section~\ref{doctest-basic-api}. @@ -267,6 +280,18 @@ set with the \programopt{-v} command-line switch or with the optional keyword argument \var{verbose}. +Since Python 2.6, there is also a command line shortcut for running +\function{testfile()}. You can instruct the Python interpreter to run +the doctest module directly from the standard library and pass the file +name(s) on the command line: + +\begin{verbatim} +python -m doctest -v example.txt +\end{verbatim} + +Because the file name does not end with \file{.py}, \module{doctest} infers +that it must be run with \function{testfile()}, not \function{testmod()}. + For more information on \function{testfile()}, see section~\ref{doctest-basic-api}. @@ -1716,7 +1741,7 @@ >>> \end{verbatim} - \versionchanged[The ability to use \code{\refmodule{pdb}.set_trace()} + \versionchanged[The ability to use \function{\refmodule{pdb}.set_trace()} usefully inside doctests was added]{2.4} \end{itemize} @@ -1800,10 +1825,10 @@ used. If \var{pm} has a true value, the script file is run directly, and the debugger gets involved only if the script terminates via raising an unhandled exception. If it does, then post-mortem debugging is invoked, - via \code{\refmodule{pdb}.post_mortem()}, passing the traceback object + via \function{\refmodule{pdb}.post_mortem()}, passing the traceback object from the unhandled exception. If \var{pm} is not specified, or is false, the script is run under the debugger from the start, via passing an - appropriate \function{execfile()} call to \code{\refmodule{pdb}.run()}. + appropriate \function{execfile()} call to \function{\refmodule{pdb}.run()}. \versionadded{2.3} Modified: python/branches/p3yk/Doc/lib/libdocxmlrpc.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libdocxmlrpc.tex (original) +++ python/branches/p3yk/Doc/lib/libdocxmlrpc.tex Fri Apr 27 21:54:29 2007 @@ -14,8 +14,12 @@ \class{DocXMLRPCServer}, or embedded in a CGI environment, using \class{DocCGIXMLRPCRequestHandler}. -\begin{classdesc}{DocXMLRPCServer}{addr\optional{, - requestHandler\optional{, logRequests}}} +\begin{classdesc}{DocXMLRPCServer}{addr\optional{, + requestHandler\optional{, + logRequests\optional{, + allow_none\optional{, + encoding\optional{, + bind_and_activate}}}}}} Create a new server instance. All parameters have the same meaning as for \class{SimpleXMLRPCServer.SimpleXMLRPCServer}; @@ -47,14 +51,14 @@ handled by generating pydoc-style HTML documentation. This allows a server to provide its own web-based documentation. -\begin{methoddesc}{set_server_title}{server_title} +\begin{methoddesc}[DocXMLRPCServer]{set_server_title}{server_title} Set the title used in the generated HTML documentation. This title will be used inside the HTML "title" element. \end{methoddesc} -\begin{methoddesc}{set_server_name}{server_name} +\begin{methoddesc}[DocXMLRPCServer]{set_server_name}{server_name} Set the name used in the generated HTML documentation. This name will appear at the top of the generated documentation inside a "h1" @@ -63,7 +67,7 @@ \end{methoddesc} -\begin{methoddesc}{set_server_documentation}{server_documentation} +\begin{methoddesc}[DocXMLRPCServer]{set_server_documentation}{server_documentation} Set the description used in the generated HTML documentation. This description will appear as a paragraph, below the server name, in the @@ -80,14 +84,14 @@ generating pydoc-style HTML documentation. This allows a server to provide its own web-based documentation. -\begin{methoddesc}{set_server_title}{server_title} +\begin{methoddesc}[DocCGIXMLRPCRequestHandler]{set_server_title}{server_title} Set the title used in the generated HTML documentation. This title will be used inside the HTML "title" element. \end{methoddesc} -\begin{methoddesc}{set_server_name}{server_name} +\begin{methoddesc}[DocCGIXMLRPCRequestHandler]{set_server_name}{server_name} Set the name used in the generated HTML documentation. This name will appear at the top of the generated documentation inside a "h1" @@ -96,7 +100,7 @@ \end{methoddesc} -\begin{methoddesc}{set_server_documentation}{server_documentation} +\begin{methoddesc}[DocCGIXMLRPCRequestHandler]{set_server_documentation}{server_documentation} Set the description used in the generated HTML documentation. This description will appear as a paragraph, below the server name, in the Modified: python/branches/p3yk/Doc/lib/libdumbdbm.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libdumbdbm.tex (original) +++ python/branches/p3yk/Doc/lib/libdumbdbm.tex Fri Apr 27 21:54:29 2007 @@ -57,7 +57,7 @@ In addition to the methods provided by the \class{UserDict.DictMixin} class, \class{dumbdbm} objects provide the following methods. -\begin{methoddesc}{sync}{} +\begin{methoddesc}[dumbdbm]{sync}{} Synchronize the on-disk directory and data files. This method is called by the \method{sync} method of \class{Shelve} objects. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libetree.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libetree.tex (original) +++ python/branches/p3yk/Doc/lib/libetree.tex Fri Apr 27 21:54:29 2007 @@ -144,12 +144,12 @@ Element objects returned by Element or SubElement have the following methods and attributes. -\begin{memberdesc}{tag} +\begin{memberdesc}[Element]{tag} A string identifying what kind of data this element represents (the element type, in other words). \end{memberdesc} -\begin{memberdesc}{text} +\begin{memberdesc}[Element]{text} The \var{text} attribute can be used to hold additional data associated with the element. As the name implies this attribute is usually a string but may be any @@ -158,7 +158,7 @@ any text found between the element tags. \end{memberdesc} -\begin{memberdesc}{tail} +\begin{memberdesc}[Element]{tail} The \var{tail} attribute can be used to hold additional data associated with the element. This attribute is usually a string but may be any application-specific object. @@ -166,7 +166,7 @@ any text found after the element's end tag and before the next tag. \end{memberdesc} -\begin{memberdesc}{attrib} +\begin{memberdesc}[Element]{attrib} A dictionary containing the element's attributes. Note that while the \var{attrib} value is always a real mutable Python dictionary, an ElementTree implementation may choose to use another @@ -177,52 +177,52 @@ The following dictionary-like methods work on the element attributes. -\begin{methoddesc}{clear}{} +\begin{methoddesc}[Element]{clear}{} Resets an element. This function removes all subelements, clears all attributes, and sets the text and tail attributes to None. \end{methoddesc} -\begin{methoddesc}{get}{key\optional{, default=None}} +\begin{methoddesc}[Element]{get}{key\optional{, default=None}} Gets the element attribute named \var{key}. Returns the attribute value, or \var{default} if the attribute was not found. \end{methoddesc} -\begin{methoddesc}{items}{} +\begin{methoddesc}[Element]{items}{} Returns the element attributes as a sequence of (name, value) pairs. The attributes are returned in an arbitrary order. \end{methoddesc} -\begin{methoddesc}{keys}{} +\begin{methoddesc}[Element]{keys}{} Returns the elements attribute names as a list. The names are returned in an arbitrary order. \end{methoddesc} -\begin{methoddesc}{set}{key, value} +\begin{methoddesc}[Element]{set}{key, value} Set the attribute \var{key} on the element to \var{value}. \end{methoddesc} The following methods work on the element's children (subelements). -\begin{methoddesc}{append}{subelement} +\begin{methoddesc}[Element]{append}{subelement} Adds the element \var{subelement} to the end of this elements internal list of subelements. \end{methoddesc} -\begin{methoddesc}{find}{match} +\begin{methoddesc}[Element]{find}{match} Finds the first subelement matching \var{match}. \var{match} may be a tag name or path. Returns an element instance or \code{None}. \end{methoddesc} -\begin{methoddesc}{findall}{match} +\begin{methoddesc}[Element]{findall}{match} Finds all subelements matching \var{match}. \var{match} may be a tag name or path. Returns an iterable yielding all matching elements in document order. \end{methoddesc} -\begin{methoddesc}{findtext}{condition\optional{, default=None}} +\begin{methoddesc}[Element]{findtext}{condition\optional{, default=None}} Finds text for the first subelement matching \var{condition}. \var{condition} may be a tag name or path. Returns the text content of the first matching element, or @@ -230,11 +230,11 @@ matching element has no text content an empty string is returned. \end{methoddesc} -\begin{methoddesc}{getchildren}{} +\begin{methoddesc}[Element]{getchildren}{} Returns all subelements. The elements are returned in document order. \end{methoddesc} -\begin{methoddesc}{getiterator}{\optional{tag=None}} +\begin{methoddesc}[Element]{getiterator}{\optional{tag=None}} Creates a tree iterator with the current element as the root. The iterator iterates over this element and all elements below it that match the given tag. If tag @@ -243,16 +243,16 @@ order. \end{methoddesc} -\begin{methoddesc}{insert}{index, element} +\begin{methoddesc}[Element]{insert}{index, element} Inserts a subelement at the given position in this element. \end{methoddesc} -\begin{methoddesc}{makeelement}{tag, attrib} +\begin{methoddesc}[Element]{makeelement}{tag, attrib} Creates a new element object of the same type as this element. Do not call this method, use the SubElement factory function instead. \end{methoddesc} -\begin{methoddesc}{remove}{subelement} +\begin{methoddesc}[Element]{remove}{subelement} Removes \var{subelement} from the element. Unlike the findXXX methods this method compares elements based on the instance identity, not on tag value or contents. Modified: python/branches/p3yk/Doc/lib/libfm.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libfm.tex (original) +++ python/branches/p3yk/Doc/lib/libfm.tex Fri Apr 27 21:54:29 2007 @@ -55,40 +55,39 @@ Font handle objects support the following operations: -\setindexsubitem{(font handle method)} -\begin{funcdesc}{scalefont}{factor} +\begin{methoddesc}[font handle]{scalefont}{factor} Returns a handle for a scaled version of this font. Calls \code{fmscalefont(\var{fh}, \var{factor})}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{setfont}{} +\begin{methoddesc}[font handle]{setfont}{} Makes this font the current font. Note: the effect is undone silently when the font handle object is deleted. Calls \code{fmsetfont(\var{fh})}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{getfontname}{} +\begin{methoddesc}[font handle]{getfontname}{} Returns this font's name. Calls \code{fmgetfontname(\var{fh})}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{getcomment}{} +\begin{methoddesc}[font handle]{getcomment}{} Returns the comment string associated with this font. Raises an exception if there is none. Calls \code{fmgetcomment(\var{fh})}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{getfontinfo}{} +\begin{methoddesc}[font handle]{getfontinfo}{} Returns a tuple giving some pertinent data about this font. This is an interface to \code{fmgetfontinfo()}. The returned tuple contains the following numbers: \code{(}\var{printermatched}, \var{fixed_width}, \var{xorig}, \var{yorig}, \var{xsize}, \var{ysize}, \var{height}, \var{nglyphs}\code{)}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{getstrwidth}{string} +\begin{methoddesc}[font handle]{getstrwidth}{string} Returns the width, in pixels, of \var{string} when drawn in this font. Calls \code{fmgetstrwidth(\var{fh}, \var{string})}. -\end{funcdesc} +\end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libfnmatch.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libfnmatch.tex (original) +++ python/branches/p3yk/Doc/lib/libfnmatch.tex Fri Apr 27 21:54:29 2007 @@ -36,6 +36,19 @@ require a case-sensitive comparison regardless of whether that's standard for your operating system, use \function{fnmatchcase()} instead. + +This example will print all file names in the current directory with the +extension \code{.txt}: + +\begin{verbatim} +import fnmatch +import os + +for file in os.listdir('.'): + if fnmatch.fnmatch(file, '*.txt'): + print file +\end{verbatim} + \end{funcdesc} \begin{funcdesc}{fnmatchcase}{filename, pattern} @@ -50,6 +63,24 @@ \versionadded{2.2} \end{funcdesc} +\begin{funcdesc}{translate}{pattern} +Return the shell-style \var{pattern} converted to a regular +expression. + +Example: + +\begin{verbatim} +>>> import fnmatch, re +>>> +>>> regex = fnmatch.translate('*.txt') +>>> regex +'.*\\.txt$' +>>> reobj = re.compile(regex) +>>> print reobj.match('foobar.txt') +<_sre.SRE_Match object at 0x...> +\end{verbatim} +\end{funcdesc} + \begin{seealso} \seemodule{glob}{\UNIX{} shell-style path expansion.} \end{seealso} Modified: python/branches/p3yk/Doc/lib/libftplib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libftplib.tex (original) +++ python/branches/p3yk/Doc/lib/libftplib.tex Fri Apr 27 21:54:29 2007 @@ -37,12 +37,15 @@ The module defines the following items: \begin{classdesc}{FTP}{\optional{host\optional{, user\optional{, - passwd\optional{, acct}}}}} + passwd\optional{, acct\optional{, timeout}}}}}} Return a new instance of the \class{FTP} class. When \var{host} is given, the method call \code{connect(\var{host})} is made. When \var{user} is given, additionally the method call \code{login(\var{user}, \var{passwd}, \var{acct})} is made (where \var{passwd} and \var{acct} default to the empty string when not given). +The optional \var{timeout} parameter specifies a timeout in seconds for the +connection attempt (if is not specified, or passed as None, the global +default timeout setting will be used). \end{classdesc} \begin{datadesc}{all_errors} @@ -92,7 +95,7 @@ \class{FTP} instances have the following methods: -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[FTP]{set_debuglevel}{level} Set the instance's debugging level. This controls the amount of debugging output printed. The default, \code{0}, produces no debugging output. A value of \code{1} produces a moderate amount of @@ -101,22 +104,28 @@ logging each line sent and received on the control connection. \end{methoddesc} -\begin{methoddesc}{connect}{host\optional{, port}} +\begin{methoddesc}[FTP]{connect}{host\optional{, port\optional{, timeout}}} Connect to the given host and port. The default port number is \code{21}, as specified by the FTP protocol specification. It is rarely needed to specify a different port number. This function should be called only once for each instance; it should not be called at all if a host was given when the instance was created. All other methods can only be used after a connection has been made. + +The optional \var{timeout} parameter specifies a timeout in seconds for +the connection attempt. If is not specified, or passed as None, the +object timeout is used (the timeout that you passed when instantiating the +class); if the object timeout is also None, the global default timeout +setting will be used. \end{methoddesc} -\begin{methoddesc}{getwelcome}{} +\begin{methoddesc}[FTP]{getwelcome}{} Return the welcome message sent by the server in reply to the initial connection. (This message sometimes contains disclaimers or help information that may be relevant to the user.) \end{methoddesc} -\begin{methoddesc}{login}{\optional{user\optional{, passwd\optional{, acct}}}} +\begin{methoddesc}[FTP]{login}{\optional{user\optional{, passwd\optional{, acct}}}} Log in as the given \var{user}. The \var{passwd} and \var{acct} parameters are optional and default to the empty string. If no \var{user} is specified, it defaults to \code{'anonymous'}. If @@ -128,23 +137,23 @@ client has logged in. \end{methoddesc} -\begin{methoddesc}{abort}{} +\begin{methoddesc}[FTP]{abort}{} Abort a file transfer that is in progress. Using this does not always work, but it's worth a try. \end{methoddesc} -\begin{methoddesc}{sendcmd}{command} +\begin{methoddesc}[FTP]{sendcmd}{command} Send a simple command string to the server and return the response string. \end{methoddesc} -\begin{methoddesc}{voidcmd}{command} +\begin{methoddesc}[FTP]{voidcmd}{command} Send a simple command string to the server and handle the response. Return nothing if a response code in the range 200--299 is received. Raise an exception otherwise. \end{methoddesc} -\begin{methoddesc}{retrbinary}{command, +\begin{methoddesc}[FTP]{retrbinary}{command, callback\optional{, maxblocksize\optional{, rest}}} Retrieve a file in binary transfer mode. \var{command} should be an appropriate \samp{RETR} command: \code{'RETR \var{filename}'}. @@ -157,7 +166,7 @@ same thing as in the \method{transfercmd()} method. \end{methoddesc} -\begin{methoddesc}{retrlines}{command\optional{, callback}} +\begin{methoddesc}[FTP]{retrlines}{command\optional{, callback}} Retrieve a file or directory listing in \ASCII{} transfer mode. \var{command} should be an appropriate \samp{RETR} command (see \method{retrbinary()}) or a \samp{LIST} command (usually just the string @@ -166,13 +175,13 @@ the line to \code{sys.stdout}. \end{methoddesc} -\begin{methoddesc}{set_pasv}{boolean} +\begin{methoddesc}[FTP]{set_pasv}{boolean} Enable ``passive'' mode if \var{boolean} is true, other disable passive mode. (In Python 2.0 and before, passive mode was off by default; in Python 2.1 and later, it is on by default.) \end{methoddesc} -\begin{methoddesc}{storbinary}{command, file\optional{, blocksize}} +\begin{methoddesc}[FTP]{storbinary}{command, file\optional{, blocksize}} Store a file in binary transfer mode. \var{command} should be an appropriate \samp{STOR} command: \code{"STOR \var{filename}"}. \var{file} is an open file object which is read until \EOF{} using its @@ -181,14 +190,14 @@ \versionchanged[default for \var{blocksize} added]{2.1} \end{methoddesc} -\begin{methoddesc}{storlines}{command, file} +\begin{methoddesc}[FTP]{storlines}{command, file} Store a file in \ASCII{} transfer mode. \var{command} should be an appropriate \samp{STOR} command (see \method{storbinary()}). Lines are read until \EOF{} from the open file object \var{file} using its \method{readline()} method to provide the data to be stored. \end{methoddesc} -\begin{methoddesc}{transfercmd}{cmd\optional{, rest}} +\begin{methoddesc}[FTP]{transfercmd}{cmd\optional{, rest}} Initiate a transfer over the data connection. If the transfer is active, send a \samp{EPRT} or \samp{PORT} command and the transfer command specified by \var{cmd}, and accept the connection. If the server is passive, @@ -210,7 +219,7 @@ simply call \method{transfercmd()} without a \var{rest} argument. \end{methoddesc} -\begin{methoddesc}{ntransfercmd}{cmd\optional{, rest}} +\begin{methoddesc}[FTP]{ntransfercmd}{cmd\optional{, rest}} Like \method{transfercmd()}, but returns a tuple of the data connection and the expected size of the data. If the expected size could not be computed, \code{None} will be returned as the expected @@ -218,14 +227,14 @@ \method{transfercmd()}. \end{methoddesc} -\begin{methoddesc}{nlst}{argument\optional{, \ldots}} +\begin{methoddesc}[FTP]{nlst}{argument\optional{, \ldots}} Return a list of files as returned by the \samp{NLST} command. The optional \var{argument} is a directory to list (default is the current server directory). Multiple arguments can be used to pass non-standard options to the \samp{NLST} command. \end{methoddesc} -\begin{methoddesc}{dir}{argument\optional{, \ldots}} +\begin{methoddesc}[FTP]{dir}{argument\optional{, \ldots}} Produce a directory listing as returned by the \samp{LIST} command, printing it to standard output. The optional \var{argument} is a directory to list (default is the current server directory). Multiple @@ -235,41 +244,41 @@ prints to \code{sys.stdout}. This method returns \code{None}. \end{methoddesc} -\begin{methoddesc}{rename}{fromname, toname} +\begin{methoddesc}[FTP]{rename}{fromname, toname} Rename file \var{fromname} on the server to \var{toname}. \end{methoddesc} -\begin{methoddesc}{delete}{filename} +\begin{methoddesc}[FTP]{delete}{filename} Remove the file named \var{filename} from the server. If successful, returns the text of the response, otherwise raises \exception{error_perm} on permission errors or \exception{error_reply} on other errors. \end{methoddesc} -\begin{methoddesc}{cwd}{pathname} +\begin{methoddesc}[FTP]{cwd}{pathname} Set the current directory on the server. \end{methoddesc} -\begin{methoddesc}{mkd}{pathname} +\begin{methoddesc}[FTP]{mkd}{pathname} Create a new directory on the server. \end{methoddesc} -\begin{methoddesc}{pwd}{} +\begin{methoddesc}[FTP]{pwd}{} Return the pathname of the current directory on the server. \end{methoddesc} -\begin{methoddesc}{rmd}{dirname} +\begin{methoddesc}[FTP]{rmd}{dirname} Remove the directory named \var{dirname} on the server. \end{methoddesc} -\begin{methoddesc}{size}{filename} +\begin{methoddesc}[FTP]{size}{filename} Request the size of the file named \var{filename} on the server. On success, the size of the file is returned as an integer, otherwise \code{None} is returned. Note that the \samp{SIZE} command is not standardized, but is supported by many common server implementations. \end{methoddesc} -\begin{methoddesc}{quit}{} +\begin{methoddesc}[FTP]{quit}{} Send a \samp{QUIT} command to the server and close the connection. This is the ``polite'' way to close a connection, but it may raise an exception of the server reponds with an error to the @@ -278,7 +287,7 @@ calls (see below). \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[FTP]{close}{} Close the connection unilaterally. This should not be applied to an already closed connection such as after a successful call to \method{quit()}. After this call the \class{FTP} instance should not Modified: python/branches/p3yk/Doc/lib/libfuncs.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libfuncs.tex (original) +++ python/branches/p3yk/Doc/lib/libfuncs.tex Fri Apr 27 21:54:29 2007 @@ -175,15 +175,15 @@ \code{\var{x} > \var{y}}. \end{funcdesc} -\begin{funcdesc}{compile}{string, filename, kind\optional{, +\begin{funcdesc}{compile}{source, filename, mode\optional{, flags\optional{, dont_inherit}}} - Compile the \var{string} into a code object. Code objects can be + Compile the \var{source} into a code object. Code objects can be executed by a call to \function{exec()} or evaluated by a call to \function{eval()}. The \var{filename} argument should give the file from which the code was read; pass some recognizable value if it wasn't read from a file (\code{''} is commonly used). - The \var{kind} argument specifies what kind of code must be - compiled; it can be \code{'exec'} if \var{string} consists of a + The \var{mode} argument specifies what kind of code must be + compiled; it can be \code{'exec'} if \var{source} consists of a sequence of statements, \code{'eval'} if it consists of a single expression, or \code{'single'} if it consists of a single interactive statement (in the latter case, expression statements @@ -198,7 +198,7 @@ The optional arguments \var{flags} and \var{dont_inherit} (which are new in Python 2.2) control which future statements (see - \pep{236}) affect the compilation of \var{string}. If neither is + \pep{236}) affect the compilation of \var{source}. If neither is present (or both are zero) the code is compiled with those future statements that are in effect in the code that is calling compile. If the \var{flags} argument is given and \var{dont_inherit} is not @@ -582,8 +582,9 @@ \begin{funcdesc}{isinstance}{object, classinfo} Return true if the \var{object} argument is an instance of the \var{classinfo} argument, or of a (direct or indirect) subclass - thereof. Also return true if \var{classinfo} is a type object and - \var{object} is an object of that type. If \var{object} is not a + thereof. Also return true if \var{classinfo} is a type object + (new-style class) and \var{object} is an object of that type or of a + (direct or indirect) subclass thereof. If \var{object} is not a class instance or an object of the given type, the function always returns false. If \var{classinfo} is neither a class object nor a type object, it may be a tuple of class or type objects, or may @@ -641,6 +642,11 @@ \warning{The contents of this dictionary should not be modified; changes may not affect the values of local variables used by the interpreter.} + + Free variables are returned by \var{locals} when it is called in + a function block. Modifications of free variables may not affect + the values used by the interpreter. Free variables are not + returned in class blocks. \end{funcdesc} \begin{funcdesc}{long}{\optional{x\optional{, radix}}} @@ -980,7 +986,7 @@ \begin{funcdesc}{reversed}{seq} Return a reverse iterator. \var{seq} must be an object which - supports the sequence protocol (the __len__() method and the + supports the sequence protocol (the \method{__len__()} method and the \method{__getitem__()} method with integer arguments starting at \code{0}). \versionadded{2.4} @@ -1148,7 +1154,7 @@ as detailed below. \end{funcdesc} -\begin{funcdesc}{type}{name, bases, dict} +\begin{funcdescni}{type}{name, bases, dict} Return a new type object. This is essentially a dynamic form of the \keyword{class} statement. The \var{name} string is the class name and becomes the \member{__name__} attribute; the \var{bases} tuple @@ -1165,7 +1171,7 @@ >>> X = type('X', (object,), dict(a=1)) \end{verbatim} \versionadded{2.2} -\end{funcdesc} +\end{funcdescni} \begin{funcdesc}{unichr}{i} Return the Unicode string of one character whose Unicode code is the Modified: python/branches/p3yk/Doc/lib/libgettext.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libgettext.tex (original) +++ python/branches/p3yk/Doc/lib/libgettext.tex Fri Apr 27 21:54:29 2007 @@ -102,9 +102,9 @@ return \var{plural} otherwise. The Plural formula is taken from the catalog header. It is a C or -Python expression that has a free variable n; the expression evaluates +Python expression that has a free variable \var{n}; the expression evaluates to the index of the plural in the catalog. See the GNU gettext -documentation for the precise syntax to be used in .po files, and the +documentation for the precise syntax to be used in \file{.po} files and the formulas for a variety of languages. \versionadded{2.3} Modified: python/branches/p3yk/Doc/lib/libhmac.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libhmac.tex (original) +++ python/branches/p3yk/Doc/lib/libhmac.tex Fri Apr 27 21:54:29 2007 @@ -15,7 +15,7 @@ Return a new hmac object. If \var{msg} is present, the method call \code{update(\var{msg})} is made. \var{digestmod} is the digest constructor or module for the HMAC object to use. It defaults to - the \code{\refmodule{hashlib}.md5} constructor. \note{The md5 hash + the \function{\refmodule{hashlib}.md5} constructor. \note{The md5 hash has known weaknesses but remains the default for backwards compatibility. Choose a better one for your application.} \end{funcdesc} Modified: python/branches/p3yk/Doc/lib/libhotshot.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libhotshot.tex (original) +++ python/branches/p3yk/Doc/lib/libhotshot.tex Fri Apr 27 21:54:29 2007 @@ -48,25 +48,25 @@ Profile objects have the following methods: -\begin{methoddesc}{addinfo}{key, value} +\begin{methoddesc}[Profile]{addinfo}{key, value} Add an arbitrary labelled value to the profile output. \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[Profile]{close}{} Close the logfile and terminate the profiler. \end{methoddesc} -\begin{methoddesc}{fileno}{} +\begin{methoddesc}[Profile]{fileno}{} Return the file descriptor of the profiler's log file. \end{methoddesc} -\begin{methoddesc}{run}{cmd} +\begin{methoddesc}[Profile]{run}{cmd} Profile an \function{exec()}-compatible string in the script environment. The globals from the \refmodule[main]{__main__} module are used as both the globals and locals for the script. \end{methoddesc} -\begin{methoddesc}{runcall}{func, *args, **keywords} +\begin{methoddesc}[Profile]{runcall}{func, *args, **keywords} Profile a single call of a callable. Additional positional and keyword arguments may be passed along; the result of the call is returned, and exceptions are @@ -75,16 +75,16 @@ \end{methoddesc} -\begin{methoddesc}{runctx}{cmd, globals, locals} +\begin{methoddesc}[Profile]{runctx}{cmd, globals, locals} Profile an \function{exec()}-compatible string in a specific environment. The string is compiled before profiling begins. \end{methoddesc} -\begin{methoddesc}{start}{} +\begin{methoddesc}[Profile]{start}{} Start the profiler. \end{methoddesc} -\begin{methoddesc}{stop}{} +\begin{methoddesc}[Profile]{stop}{} Stop the profiler. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libhtmllib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libhtmllib.tex (original) +++ python/branches/p3yk/Doc/lib/libhtmllib.tex Fri Apr 27 21:54:29 2007 @@ -96,11 +96,11 @@ In addition to tag methods, the \class{HTMLParser} class provides some additional methods and instance variables for use within tag methods. -\begin{memberdesc}{formatter} +\begin{memberdesc}[HTMLParser]{formatter} This is the formatter instance associated with the parser. \end{memberdesc} -\begin{memberdesc}{nofill} +\begin{memberdesc}[HTMLParser]{nofill} Boolean flag which should be true when whitespace should not be collapsed, or false when it should be. In general, this should only be true when character data is to be treated as ``preformatted'' text, @@ -109,7 +109,7 @@ \end{memberdesc} -\begin{methoddesc}{anchor_bgn}{href, name, type} +\begin{methoddesc}[HTMLParser]{anchor_bgn}{href, name, type} This method is called at the start of an anchor region. The arguments correspond to the attributes of the \code{} tag with the same names. The default implementation maintains a list of hyperlinks @@ -118,27 +118,27 @@ \member{anchorlist}. \end{methoddesc} -\begin{methoddesc}{anchor_end}{} +\begin{methoddesc}[HTMLParser]{anchor_end}{} This method is called at the end of an anchor region. The default implementation adds a textual footnote marker using an index into the list of hyperlinks created by \method{anchor_bgn()}. \end{methoddesc} -\begin{methoddesc}{handle_image}{source, alt\optional{, ismap\optional{, +\begin{methoddesc}[HTMLParser]{handle_image}{source, alt\optional{, ismap\optional{, align\optional{, width\optional{, height}}}}} This method is called to handle images. The default implementation simply passes the \var{alt} value to the \method{handle_data()} method. \end{methoddesc} -\begin{methoddesc}{save_bgn}{} +\begin{methoddesc}[HTMLParser]{save_bgn}{} Begins saving character data in a buffer instead of sending it to the formatter object. Retrieve the stored data via \method{save_end()}. Use of the \method{save_bgn()} / \method{save_end()} pair may not be nested. \end{methoddesc} -\begin{methoddesc}{save_end}{} +\begin{methoddesc}[HTMLParser]{save_end}{} Ends buffering character data and returns all data saved since the preceding call to \method{save_bgn()}. If the \member{nofill} flag is false, whitespace is collapsed to single spaces. A call to this Modified: python/branches/p3yk/Doc/lib/libhtmlparser.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libhtmlparser.tex (original) +++ python/branches/p3yk/Doc/lib/libhtmlparser.tex Fri Apr 27 21:54:29 2007 @@ -75,14 +75,18 @@ be overridden by a derived class; the base class implementation does nothing. -The \var{tag} argument is the name of the tag converted to -lower case. The \var{attrs} argument is a list of \code{(\var{name}, -\var{value})} pairs containing the attributes found inside the tag's -\code{<>} brackets. The \var{name} will be translated to lower case -and double quotes and backslashes in the \var{value} have been -interpreted. For instance, for the tag \code{}, this method would be called as +The \var{tag} argument is the name of the tag converted to lower case. +The \var{attrs} argument is a list of \code{(\var{name}, \var{value})} +pairs containing the attributes found inside the tag's \code{<>} +brackets. The \var{name} will be translated to lower case, and quotes +in the \var{value} have been removed, and character and entity +references have been replaced. For instance, for the tag \code{}, this method would be called as \samp{handle_starttag('a', [('href', 'http://www.cwi.nl/')])}. + +\versionchanged[All entity references from htmlentitydefs are now +replaced in the attribute values]{2.6} + \end{methoddesc} \begin{methoddesc}{handle_startendtag}{tag, attrs} Modified: python/branches/p3yk/Doc/lib/libhttplib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libhttplib.tex (original) +++ python/branches/p3yk/Doc/lib/libhttplib.tex Fri Apr 27 21:54:29 2007 @@ -26,18 +26,27 @@ The module provides the following classes: -\begin{classdesc}{HTTPConnection}{host\optional{, port}} +\begin{classdesc}{HTTPConnection}{host\optional{, port\optional{, + strict\optional{, timeout}}}} An \class{HTTPConnection} instance represents one transaction with an HTTP server. It should be instantiated passing it a host and optional port number. If no port number is passed, the port is extracted from the host string if it has the form \code{\var{host}:\var{port}}, else the default HTTP port (80) is -used. For example, the following calls all create instances that connect to +used. When True, the optional parameter \var{strict} +causes \code{BadStatusLine} to be raised if the status line can't be parsed +as a valid HTTP/1.0 or 1.1 status line. If the optional \var{timeout} +parameter is given, connection attempts will timeout after that many +seconds (if it is not given or \code{None}, the global default +timeout setting is used). + +For example, the following calls all create instances that connect to the server at the same host and port: \begin{verbatim} >>> h1 = httplib.HTTPConnection('www.cwi.nl') >>> h2 = httplib.HTTPConnection('www.cwi.nl:80') >>> h3 = httplib.HTTPConnection('www.cwi.nl', 80) +>>> h3 = httplib.HTTPConnection('www.cwi.nl', 80, timeout=10) \end{verbatim} \versionadded{2.0} \end{classdesc} @@ -300,7 +309,7 @@ \class{HTTPConnection} instances have the following methods: -\begin{methoddesc}{request}{method, url\optional{, body\optional{, headers}}} +\begin{methoddesc}[HTTPConnection]{request}{method, url\optional{, body\optional{, headers}}} This will send a request to the server using the HTTP request method \var{method} and the selector \var{url}. If the \var{body} argument is present, it should be a string of data to send after the headers are finished. @@ -314,24 +323,24 @@ \versionchanged[\var{body} can be a file object]{2.6} \end{methoddesc} -\begin{methoddesc}{getresponse}{} +\begin{methoddesc}[HTTPConnection]{getresponse}{} Should be called after a request is sent to get the response from the server. Returns an \class{HTTPResponse} instance. \note{Note that you must have read the whole response before you can send a new request to the server.} \end{methoddesc} -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[HTTPConnection]{set_debuglevel}{level} Set the debugging level (the amount of debugging output printed). The default debug level is \code{0}, meaning no debugging output is printed. \end{methoddesc} -\begin{methoddesc}{connect}{} +\begin{methoddesc}[HTTPConnection]{connect}{} Connect to the server specified when the object was created. \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[HTTPConnection]{close}{} Close the connection to the server. \end{methoddesc} @@ -339,7 +348,7 @@ you can also send your request step by step, by using the four functions below. -\begin{methoddesc}{putrequest}{request, selector\optional{, +\begin{methoddesc}[HTTPConnection]{putrequest}{request, selector\optional{, skip\_host\optional{, skip_accept_encoding}}} This should be the first call after the connection to the server has been made. It sends a line to the server consisting of the @@ -351,18 +360,18 @@ \versionchanged[\var{skip_accept_encoding} argument added]{2.4} \end{methoddesc} -\begin{methoddesc}{putheader}{header, argument\optional{, ...}} +\begin{methoddesc}[HTTPConnection]{putheader}{header, argument\optional{, ...}} Send an \rfc{822}-style header to the server. It sends a line to the server consisting of the header, a colon and a space, and the first argument. If more arguments are given, continuation lines are sent, each consisting of a tab and an argument. \end{methoddesc} -\begin{methoddesc}{endheaders}{} +\begin{methoddesc}[HTTPConnection]{endheaders}{} Send a blank line to the server, signalling the end of the headers. \end{methoddesc} -\begin{methoddesc}{send}{data} +\begin{methoddesc}[HTTPConnection]{send}{data} Send data to the server. This should be used directly only after the \method{endheaders()} method has been called and before \method{getresponse()} is called. @@ -372,34 +381,34 @@ \class{HTTPResponse} instances have the following methods and attributes: -\begin{methoddesc}{read}{\optional{amt}} +\begin{methoddesc}[HTTPResponse]{read}{\optional{amt}} Reads and returns the response body, or up to the next \var{amt} bytes. \end{methoddesc} -\begin{methoddesc}{getheader}{name\optional{, default}} +\begin{methoddesc}[HTTPResponse]{getheader}{name\optional{, default}} Get the contents of the header \var{name}, or \var{default} if there is no matching header. \end{methoddesc} -\begin{methoddesc}{getheaders}{} +\begin{methoddesc}[HTTPResponse]{getheaders}{} Return a list of (header, value) tuples. \versionadded{2.4} \end{methoddesc} -\begin{datadesc}{msg} +\begin{memberdesc}[HTTPResponse]{msg} A \class{mimetools.Message} instance containing the response headers. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{version} +\begin{memberdesc}[HTTPResponse]{version} HTTP protocol version used by server. 10 for HTTP/1.0, 11 for HTTP/1.1. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{status} +\begin{memberdesc}[HTTPResponse]{status} Status code returned by server. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{reason} +\begin{memberdesc}[HTTPResponse]{reason} Reason phrase returned by server. -\end{datadesc} +\end{memberdesc} \subsection{Examples \label{httplib-examples}} Modified: python/branches/p3yk/Doc/lib/libimaplib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libimaplib.tex (original) +++ python/branches/p3yk/Doc/lib/libimaplib.tex Fri Apr 27 21:54:29 2007 @@ -153,11 +153,11 @@ An \class{IMAP4} instance has the following methods: -\begin{methoddesc}{append}{mailbox, flags, date_time, message} +\begin{methoddesc}[IMAP4]{append}{mailbox, flags, date_time, message} Append \var{message} to named mailbox. \end{methoddesc} -\begin{methoddesc}{authenticate}{mechanism, authobject} +\begin{methoddesc}[IMAP4]{authenticate}{mechanism, authobject} Authenticate command --- requires response processing. \var{mechanism} specifies which authentication mechanism is to be @@ -176,115 +176,115 @@ be sent instead. \end{methoddesc} -\begin{methoddesc}{check}{} +\begin{methoddesc}[IMAP4]{check}{} Checkpoint mailbox on server. \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[IMAP4]{close}{} Close currently selected mailbox. Deleted messages are removed from writable mailbox. This is the recommended command before \samp{LOGOUT}. \end{methoddesc} -\begin{methoddesc}{copy}{message_set, new_mailbox} +\begin{methoddesc}[IMAP4]{copy}{message_set, new_mailbox} Copy \var{message_set} messages onto end of \var{new_mailbox}. \end{methoddesc} -\begin{methoddesc}{create}{mailbox} +\begin{methoddesc}[IMAP4]{create}{mailbox} Create new mailbox named \var{mailbox}. \end{methoddesc} -\begin{methoddesc}{delete}{mailbox} +\begin{methoddesc}[IMAP4]{delete}{mailbox} Delete old mailbox named \var{mailbox}. \end{methoddesc} -\begin{methoddesc}{deleteacl}{mailbox, who} +\begin{methoddesc}[IMAP4]{deleteacl}{mailbox, who} Delete the ACLs (remove any rights) set for who on mailbox. \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{expunge}{} +\begin{methoddesc}[IMAP4]{expunge}{} Permanently remove deleted items from selected mailbox. Generates an \samp{EXPUNGE} response for each deleted message. Returned data contains a list of \samp{EXPUNGE} message numbers in order received. \end{methoddesc} -\begin{methoddesc}{fetch}{message_set, message_parts} +\begin{methoddesc}[IMAP4]{fetch}{message_set, message_parts} Fetch (parts of) messages. \var{message_parts} should be a string of message part names enclosed within parentheses, eg: \samp{"(UID BODY[TEXT])"}. Returned data are tuples of message part envelope and data. \end{methoddesc} -\begin{methoddesc}{getacl}{mailbox} +\begin{methoddesc}[IMAP4]{getacl}{mailbox} Get the \samp{ACL}s for \var{mailbox}. The method is non-standard, but is supported by the \samp{Cyrus} server. \end{methoddesc} -\begin{methoddesc}{getannotation}{mailbox, entry, attribute} +\begin{methoddesc}[IMAP4]{getannotation}{mailbox, entry, attribute} Retrieve the specified \samp{ANNOTATION}s for \var{mailbox}. The method is non-standard, but is supported by the \samp{Cyrus} server. \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}{getquota}{root} +\begin{methoddesc}[IMAP4]{getquota}{root} Get the \samp{quota} \var{root}'s resource usage and limits. This method is part of the IMAP4 QUOTA extension defined in rfc2087. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{getquotaroot}{mailbox} +\begin{methoddesc}[IMAP4]{getquotaroot}{mailbox} Get the list of \samp{quota} \samp{roots} for the named \var{mailbox}. This method is part of the IMAP4 QUOTA extension defined in rfc2087. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{list}{\optional{directory\optional{, pattern}}} +\begin{methoddesc}[IMAP4]{list}{\optional{directory\optional{, pattern}}} List mailbox names in \var{directory} matching \var{pattern}. \var{directory} defaults to the top-level mail folder, and \var{pattern} defaults to match anything. Returned data contains a list of \samp{LIST} responses. \end{methoddesc} -\begin{methoddesc}{login}{user, password} +\begin{methoddesc}[IMAP4]{login}{user, password} Identify the client using a plaintext password. The \var{password} will be quoted. \end{methoddesc} -\begin{methoddesc}{login_cram_md5}{user, password} +\begin{methoddesc}[IMAP4]{login_cram_md5}{user, password} Force use of \samp{CRAM-MD5} authentication when identifying the client to protect the password. Will only work if the server \samp{CAPABILITY} response includes the phrase \samp{AUTH=CRAM-MD5}. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{logout}{} +\begin{methoddesc}[IMAP4]{logout}{} Shutdown connection to server. Returns server \samp{BYE} response. \end{methoddesc} -\begin{methoddesc}{lsub}{\optional{directory\optional{, pattern}}} +\begin{methoddesc}[IMAP4]{lsub}{\optional{directory\optional{, pattern}}} List subscribed mailbox names in directory matching pattern. \var{directory} defaults to the top level directory and \var{pattern} defaults to match any mailbox. Returned data are tuples of message part envelope and data. \end{methoddesc} -\begin{methoddesc}{myrights}{mailbox} +\begin{methoddesc}[IMAP4]{myrights}{mailbox} Show my ACLs for a mailbox (i.e. the rights that I have on mailbox). \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{namespace}{} +\begin{methoddesc}[IMAP4]{namespace}{} Returns IMAP namespaces as defined in RFC2342. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{noop}{} +\begin{methoddesc}[IMAP4]{noop}{} Send \samp{NOOP} to server. \end{methoddesc} -\begin{methoddesc}{open}{host, port} +\begin{methoddesc}[IMAP4]{open}{host, port} Opens socket to \var{port} at \var{host}. The connection objects established by this method will be used in the \code{read}, \code{readline}, \code{send}, and @@ -292,42 +292,42 @@ You may override this method. \end{methoddesc} -\begin{methoddesc}{partial}{message_num, message_part, start, length} +\begin{methoddesc}[IMAP4]{partial}{message_num, message_part, start, length} Fetch truncated part of a message. Returned data is a tuple of message part envelope and data. \end{methoddesc} -\begin{methoddesc}{proxyauth}{user} +\begin{methoddesc}[IMAP4]{proxyauth}{user} Assume authentication as \var{user}. Allows an authorised administrator to proxy into any user's mailbox. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{read}{size} +\begin{methoddesc}[IMAP4]{read}{size} Reads \var{size} bytes from the remote server. You may override this method. \end{methoddesc} -\begin{methoddesc}{readline}{} +\begin{methoddesc}[IMAP4]{readline}{} Reads one line from the remote server. You may override this method. \end{methoddesc} -\begin{methoddesc}{recent}{} +\begin{methoddesc}[IMAP4]{recent}{} Prompt server for an update. Returned data is \code{None} if no new messages, else value of \samp{RECENT} response. \end{methoddesc} -\begin{methoddesc}{rename}{oldmailbox, newmailbox} +\begin{methoddesc}[IMAP4]{rename}{oldmailbox, newmailbox} Rename mailbox named \var{oldmailbox} to \var{newmailbox}. \end{methoddesc} -\begin{methoddesc}{response}{code} +\begin{methoddesc}[IMAP4]{response}{code} Return data for response \var{code} if received, or \code{None}. Returns the given code, instead of the usual type. \end{methoddesc} -\begin{methoddesc}{search}{charset, criterion\optional{, ...}} +\begin{methoddesc}[IMAP4]{search}{charset, criterion\optional{, ...}} Search mailbox for matching messages. \var{charset} may be \code{None}, in which case no \samp{CHARSET} will be specified in the request to the server. The IMAP protocol requires that at least one @@ -345,45 +345,45 @@ \end{verbatim} \end{methoddesc} -\begin{methoddesc}{select}{\optional{mailbox\optional{, readonly}}} +\begin{methoddesc}[IMAP4]{select}{\optional{mailbox\optional{, readonly}}} Select a mailbox. Returned data is the count of messages in \var{mailbox} (\samp{EXISTS} response). The default \var{mailbox} is \code{'INBOX'}. If the \var{readonly} flag is set, modifications to the mailbox are not allowed. \end{methoddesc} -\begin{methoddesc}{send}{data} +\begin{methoddesc}[IMAP4]{send}{data} Sends \code{data} to the remote server. You may override this method. \end{methoddesc} -\begin{methoddesc}{setacl}{mailbox, who, what} +\begin{methoddesc}[IMAP4]{setacl}{mailbox, who, what} Set an \samp{ACL} for \var{mailbox}. The method is non-standard, but is supported by the \samp{Cyrus} server. \end{methoddesc} -\begin{methoddesc}{setannotation}{mailbox, entry, attribute\optional{, ...}} +\begin{methoddesc}[IMAP4]{setannotation}{mailbox, entry, attribute\optional{, ...}} Set \samp{ANNOTATION}s for \var{mailbox}. The method is non-standard, but is supported by the \samp{Cyrus} server. \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}{setquota}{root, limits} +\begin{methoddesc}[IMAP4]{setquota}{root, limits} Set the \samp{quota} \var{root}'s resource \var{limits}. This method is part of the IMAP4 QUOTA extension defined in rfc2087. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{shutdown}{} +\begin{methoddesc}[IMAP4]{shutdown}{} Close connection established in \code{open}. You may override this method. \end{methoddesc} -\begin{methoddesc}{socket}{} +\begin{methoddesc}[IMAP4]{socket}{} Returns socket instance used to connect to server. \end{methoddesc} -\begin{methoddesc}{sort}{sort_criteria, charset, search_criterion\optional{, ...}} +\begin{methoddesc}[IMAP4]{sort}{sort_criteria, charset, search_criterion\optional{, ...}} The \code{sort} command is a variant of \code{search} with sorting semantics for the results. Returned data contains a space separated list of matching message numbers. @@ -402,11 +402,11 @@ This is an \samp{IMAP4rev1} extension command. \end{methoddesc} -\begin{methoddesc}{status}{mailbox, names} +\begin{methoddesc}[IMAP4]{status}{mailbox, names} Request named status conditions for \var{mailbox}. \end{methoddesc} -\begin{methoddesc}{store}{message_set, command, flag_list} +\begin{methoddesc}[IMAP4]{store}{message_set, command, flag_list} Alters flag dispositions for messages in mailbox. \var{command} is specified by section 6.4.6 of \rfc{2060} as being one of "FLAGS", "+FLAGS", or "-FLAGS", optionally with a suffix of ".SILENT". @@ -421,11 +421,11 @@ \end{verbatim} \end{methoddesc} -\begin{methoddesc}{subscribe}{mailbox} +\begin{methoddesc}[IMAP4]{subscribe}{mailbox} Subscribe to new mailbox. \end{methoddesc} -\begin{methoddesc}{thread}{threading_algorithm, charset, +\begin{methoddesc}[IMAP4]{thread}{threading_algorithm, charset, search_criterion\optional{, ...}} The \code{thread} command is a variant of \code{search} with threading semantics for the results. Returned data contains a space @@ -448,18 +448,18 @@ This is an \samp{IMAP4rev1} extension command. \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{uid}{command, arg\optional{, ...}} +\begin{methoddesc}[IMAP4]{uid}{command, arg\optional{, ...}} Execute command args with messages identified by UID, rather than message number. Returns response appropriate to command. At least one argument must be supplied; if none are provided, the server will return an error and an exception will be raised. \end{methoddesc} -\begin{methoddesc}{unsubscribe}{mailbox} +\begin{methoddesc}[IMAP4]{unsubscribe}{mailbox} Unsubscribe from old mailbox. \end{methoddesc} -\begin{methoddesc}{xatom}{name\optional{, arg\optional{, ...}}} +\begin{methoddesc}[IMAP4]{xatom}{name\optional{, arg\optional{, ...}}} Allow simple extension commands notified by server in \samp{CAPABILITY} response. \end{methoddesc} @@ -467,7 +467,7 @@ Instances of \class{IMAP4_SSL} have just one additional method: -\begin{methoddesc}{ssl}{} +\begin{methoddesc}[IMAP4_SSL]{ssl}{} Returns SSLObject instance used for the secure connection with the server. \end{methoddesc} @@ -475,12 +475,12 @@ The following attributes are defined on instances of \class{IMAP4}: -\begin{memberdesc}{PROTOCOL_VERSION} +\begin{memberdesc}[IMAP4]{PROTOCOL_VERSION} The most recent supported protocol in the \samp{CAPABILITY} response from the server. \end{memberdesc} -\begin{memberdesc}{debug} +\begin{memberdesc}[IMAP4]{debug} Integer value to control debugging output. The initialize value is taken from the module variable \code{Debug}. Values greater than three trace each command. Modified: python/branches/p3yk/Doc/lib/liblogging.tex ============================================================================== --- python/branches/p3yk/Doc/lib/liblogging.tex (original) +++ python/branches/p3yk/Doc/lib/liblogging.tex Fri Apr 27 21:54:29 2007 @@ -364,13 +364,13 @@ never instantiated directly, but always through the module-level function \function{logging.getLogger(name)}. -\begin{datadesc}{propagate} +\begin{memberdesc}[Logger]{propagate} If this evaluates to false, logging messages are not passed by this logger or by child loggers to higher level (ancestor) loggers. The constructor sets this attribute to 1. -\end{datadesc} +\end{memberdesc} -\begin{methoddesc}{setLevel}{lvl} +\begin{methoddesc}[Logger]{setLevel}{lvl} Sets the threshold for this logger to \var{lvl}. Logging messages which are less severe than \var{lvl} will be ignored. When a logger is created, the level is set to \constant{NOTSET} (which causes all messages @@ -393,21 +393,21 @@ as the effective level. \end{methoddesc} -\begin{methoddesc}{isEnabledFor}{lvl} +\begin{methoddesc}[Logger]{isEnabledFor}{lvl} Indicates if a message of severity \var{lvl} would be processed by this logger. This method checks first the module-level level set by \function{logging.disable(lvl)} and then the logger's effective level as determined by \method{getEffectiveLevel()}. \end{methoddesc} -\begin{methoddesc}{getEffectiveLevel}{} +\begin{methoddesc}[Logger]{getEffectiveLevel}{} Indicates the effective level for this logger. If a value other than \constant{NOTSET} has been set using \method{setLevel()}, it is returned. Otherwise, the hierarchy is traversed towards the root until a value other than \constant{NOTSET} is found, and that value is returned. \end{methoddesc} -\begin{methoddesc}{debug}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{debug}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{DEBUG} on this logger. The \var{msg} is the message format string, and the \var{args} are the arguments which are merged into \var{msg} using the string formatting @@ -462,67 +462,67 @@ \end{methoddesc} -\begin{methoddesc}{info}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{info}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{INFO} on this logger. The arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{warning}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{warning}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{WARNING} on this logger. The arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{error}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{error}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{ERROR} on this logger. The arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{critical}{msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{critical}{msg\optional{, *args\optional{, **kwargs}}} Logs a message with level \constant{CRITICAL} on this logger. The arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{log}{lvl, msg\optional{, *args\optional{, **kwargs}}} +\begin{methoddesc}[Logger]{log}{lvl, msg\optional{, *args\optional{, **kwargs}}} Logs a message with integer level \var{lvl} on this logger. The other arguments are interpreted as for \method{debug()}. \end{methoddesc} -\begin{methoddesc}{exception}{msg\optional{, *args}} +\begin{methoddesc}[Logger]{exception}{msg\optional{, *args}} Logs a message with level \constant{ERROR} on this logger. The arguments are interpreted as for \method{debug()}. Exception info is added to the logging message. This method should only be called from an exception handler. \end{methoddesc} -\begin{methoddesc}{addFilter}{filt} +\begin{methoddesc}[Logger]{addFilter}{filt} Adds the specified filter \var{filt} to this logger. \end{methoddesc} -\begin{methoddesc}{removeFilter}{filt} +\begin{methoddesc}[Logger]{removeFilter}{filt} Removes the specified filter \var{filt} from this logger. \end{methoddesc} -\begin{methoddesc}{filter}{record} +\begin{methoddesc}[Logger]{filter}{record} Applies this logger's filters to the record and returns a true value if the record is to be processed. \end{methoddesc} -\begin{methoddesc}{addHandler}{hdlr} +\begin{methoddesc}[Logger]{addHandler}{hdlr} Adds the specified handler \var{hdlr} to this logger. \end{methoddesc} -\begin{methoddesc}{removeHandler}{hdlr} +\begin{methoddesc}[Logger]{removeHandler}{hdlr} Removes the specified handler \var{hdlr} from this logger. \end{methoddesc} -\begin{methoddesc}{findCaller}{} +\begin{methoddesc}[Logger]{findCaller}{} Finds the caller's source filename and line number. Returns the filename, line number and function name as a 3-element tuple. \versionchanged[The function name was added. In earlier versions, the filename and line number were returned as a 2-element tuple.]{2.5} \end{methoddesc} -\begin{methoddesc}{handle}{record} +\begin{methoddesc}[Logger]{handle}{record} Handles a record by passing it to all handlers associated with this logger and its ancestors (until a false value of \var{propagate} is found). This method is used for unpickled records received from a socket, as well @@ -530,8 +530,8 @@ \method{filter()}. \end{methoddesc} -\begin{methoddesc}{makeRecord}{name, lvl, fn, lno, msg, args, exc_info - \optional{, func, extra}} +\begin{methoddesc}[Logger]{makeRecord}{name, lvl, fn, lno, msg, args, exc_info + \optional{, func, extra}} This is a factory method which can be overridden in subclasses to create specialized \class{LogRecord} instances. \versionchanged[\var{func} and \var{extra} were added]{2.5} @@ -875,66 +875,66 @@ base for more useful subclasses. However, the \method{__init__()} method in subclasses needs to call \method{Handler.__init__()}. -\begin{methoddesc}{__init__}{level=\constant{NOTSET}} +\begin{methoddesc}[Handler]{__init__}{level=\constant{NOTSET}} Initializes the \class{Handler} instance by setting its level, setting the list of filters to the empty list and creating a lock (using \method{createLock()}) for serializing access to an I/O mechanism. \end{methoddesc} -\begin{methoddesc}{createLock}{} +\begin{methoddesc}[Handler]{createLock}{} Initializes a thread lock which can be used to serialize access to underlying I/O functionality which may not be threadsafe. \end{methoddesc} -\begin{methoddesc}{acquire}{} +\begin{methoddesc}[Handler]{acquire}{} Acquires the thread lock created with \method{createLock()}. \end{methoddesc} -\begin{methoddesc}{release}{} +\begin{methoddesc}[Handler]{release}{} Releases the thread lock acquired with \method{acquire()}. \end{methoddesc} -\begin{methoddesc}{setLevel}{lvl} +\begin{methoddesc}[Handler]{setLevel}{lvl} Sets the threshold for this handler to \var{lvl}. Logging messages which are less severe than \var{lvl} will be ignored. When a handler is created, the level is set to \constant{NOTSET} (which causes all messages to be processed). \end{methoddesc} -\begin{methoddesc}{setFormatter}{form} +\begin{methoddesc}[Handler]{setFormatter}{form} Sets the \class{Formatter} for this handler to \var{form}. \end{methoddesc} -\begin{methoddesc}{addFilter}{filt} +\begin{methoddesc}[Handler]{addFilter}{filt} Adds the specified filter \var{filt} to this handler. \end{methoddesc} -\begin{methoddesc}{removeFilter}{filt} +\begin{methoddesc}[Handler]{removeFilter}{filt} Removes the specified filter \var{filt} from this handler. \end{methoddesc} -\begin{methoddesc}{filter}{record} +\begin{methoddesc}[Handler]{filter}{record} Applies this handler's filters to the record and returns a true value if the record is to be processed. \end{methoddesc} -\begin{methoddesc}{flush}{} +\begin{methoddesc}[Handler]{flush}{} Ensure all logging output has been flushed. This version does nothing and is intended to be implemented by subclasses. \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[Handler]{close}{} Tidy up any resources used by the handler. This version does nothing and is intended to be implemented by subclasses. \end{methoddesc} -\begin{methoddesc}{handle}{record} +\begin{methoddesc}[Handler]{handle}{record} Conditionally emits the specified logging record, depending on filters which may have been added to the handler. Wraps the actual emission of the record with acquisition/release of the I/O thread lock. \end{methoddesc} -\begin{methoddesc}{handleError}{record} +\begin{methoddesc}[Handler]{handleError}{record} This method should be called from handlers when an exception is encountered during an \method{emit()} call. By default it does nothing, which means that exceptions get silently ignored. This is what is @@ -945,12 +945,12 @@ processed when the exception occurred. \end{methoddesc} -\begin{methoddesc}{format}{record} +\begin{methoddesc}[Handler]{format}{record} Do formatting for a record - if a formatter is set, use it. Otherwise, use the default formatter for the module. \end{methoddesc} -\begin{methoddesc}{emit}{record} +\begin{methoddesc}[Handler]{emit}{record} Do whatever it takes to actually log the specified logging record. This version is intended to be implemented by subclasses and so raises a \exception{NotImplementedError}. @@ -1138,9 +1138,6 @@ Closes the socket. \end{methoddesc} -\begin{methoddesc}{handleError}{} -\end{methoddesc} - \begin{methoddesc}{emit}{} Pickles the record's attribute dictionary and writes it to the socket in binary format. If there is an error with the socket, silently drops the Modified: python/branches/p3yk/Doc/lib/libmailbox.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libmailbox.tex (original) +++ python/branches/p3yk/Doc/lib/libmailbox.tex Fri Apr 27 21:54:29 2007 @@ -1203,7 +1203,6 @@ \end{tableii} \subsection{Exceptions} -\label{mailbox-deprecated} The following exception classes are defined in the \module{mailbox} module: @@ -1247,7 +1246,7 @@ Older mailbox objects support only iteration and provide a single public method: -\begin{methoddesc}{next}{} +\begin{methoddesc}[oldmailbox]{next}{} Return the next message in the mailbox, created with the optional \var{factory} argument passed into the mailbox object's constructor. By default this is an \class{rfc822.Message} object (see the \refmodule{rfc822} module). Depending @@ -1286,13 +1285,13 @@ separated by any line that begins exactly with the string \code{'From '} (note the trailing space) if preceded by exactly two newlines. Because of the wide-range of variations in practice, nothing else on -the From_ line should be considered. However, the current +the \samp{From_} line should be considered. However, the current implementation doesn't check for the leading two newlines. This is usually fine for most applications. The \class{UnixMailbox} class implements a more strict version of -From_ line checking, using a regular expression that usually correctly -matched From_ delimiters. It considers delimiter line to be separated +\samp{From_} line checking, using a regular expression that usually correctly +matched \samp{From_} delimiters. It considers delimiter line to be separated by \samp{From \var{name} \var{time}} lines. For maximum portability, use the \class{PortableUnixMailbox} class instead. This class is identical to \class{UnixMailbox} except that individual messages are Modified: python/branches/p3yk/Doc/lib/libmimetools.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libmimetools.tex (original) +++ python/branches/p3yk/Doc/lib/libmimetools.tex Fri Apr 27 21:54:29 2007 @@ -76,7 +76,7 @@ The \class{Message} class defines the following methods in addition to the \class{rfc822.Message} methods: -\begin{methoddesc}{getplist}{} +\begin{methoddesc}[Message]{getplist}{} Return the parameter list of the \mailheader{Content-Type} header. This is a list of strings. For parameters of the form \samp{\var{key}=\var{value}}, \var{key} is converted to lower case but @@ -86,34 +86,34 @@ 'spam=2', 'Spam']}. \end{methoddesc} -\begin{methoddesc}{getparam}{name} +\begin{methoddesc}[Message]{getparam}{name} Return the \var{value} of the first parameter (as returned by \method{getplist()}) of the form \samp{\var{name}=\var{value}} for the given \var{name}. If \var{value} is surrounded by quotes of the form `\code{<}...\code{>}' or `\code{"}...\code{"}', these are removed. \end{methoddesc} -\begin{methoddesc}{getencoding}{} +\begin{methoddesc}[Message]{getencoding}{} Return the encoding specified in the \mailheader{Content-Transfer-Encoding} message header. If no such header exists, return \code{'7bit'}. The encoding is converted to lower case. \end{methoddesc} -\begin{methoddesc}{gettype}{} +\begin{methoddesc}[Message]{gettype}{} Return the message type (of the form \samp{\var{type}/\var{subtype}}) as specified in the \mailheader{Content-Type} header. If no such header exists, return \code{'text/plain'}. The type is converted to lower case. \end{methoddesc} -\begin{methoddesc}{getmaintype}{} +\begin{methoddesc}[Message]{getmaintype}{} Return the main type as specified in the \mailheader{Content-Type} header. If no such header exists, return \code{'text'}. The main type is converted to lower case. \end{methoddesc} -\begin{methoddesc}{getsubtype}{} +\begin{methoddesc}[Message]{getsubtype}{} Return the subtype as specified in the \mailheader{Content-Type} header. If no such header exists, return \code{'plain'}. The subtype is converted to lower case. Modified: python/branches/p3yk/Doc/lib/libmimetypes.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libmimetypes.tex (original) +++ python/branches/p3yk/Doc/lib/libmimetypes.tex Fri Apr 27 21:54:29 2007 @@ -178,49 +178,49 @@ \class{MimeTypes} instances provide an interface which is very like that of the \refmodule{mimetypes} module. -\begin{datadesc}{suffix_map} +\begin{memberdesc}[MimeTypes]{suffix_map} Dictionary mapping suffixes to suffixes. This is used to allow recognition of encoded files for which the encoding and the type are indicated by the same extension. For example, the \file{.tgz} extension is mapped to \file{.tar.gz} to allow the encoding and type to be recognized separately. This is initially a copy of the global \code{suffix_map} defined in the module. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{encodings_map} +\begin{memberdesc}[MimeTypes]{encodings_map} Dictionary mapping filename extensions to encoding types. This is initially a copy of the global \code{encodings_map} defined in the module. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{types_map} +\begin{memberdesc}[MimeTypes]{types_map} Dictionary mapping filename extensions to MIME types. This is initially a copy of the global \code{types_map} defined in the module. -\end{datadesc} +\end{memberdesc} -\begin{datadesc}{common_types} +\begin{memberdesc}[MimeTypes]{common_types} Dictionary mapping filename extensions to non-standard, but commonly found MIME types. This is initially a copy of the global \code{common_types} defined in the module. -\end{datadesc} +\end{memberdesc} -\begin{methoddesc}{guess_extension}{type\optional{, strict}} +\begin{methoddesc}[MimeTypes]{guess_extension}{type\optional{, strict}} Similar to the \function{guess_extension()} function, using the tables stored as part of the object. \end{methoddesc} -\begin{methoddesc}{guess_type}{url\optional{, strict}} +\begin{methoddesc}[MimeTypes]{guess_type}{url\optional{, strict}} Similar to the \function{guess_type()} function, using the tables stored as part of the object. \end{methoddesc} -\begin{methoddesc}{read}{path} +\begin{methoddesc}[MimeTypes]{read}{path} Load MIME information from a file named \var{path}. This uses \method{readfp()} to parse the file. \end{methoddesc} -\begin{methoddesc}{readfp}{file} +\begin{methoddesc}[MimeTypes]{readfp}{file} Load MIME type information from an open file. The file must have the format of the standard \file{mime.types} files. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libmimewriter.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libmimewriter.tex (original) +++ python/branches/p3yk/Doc/lib/libmimewriter.tex Fri Apr 27 21:54:29 2007 @@ -31,7 +31,7 @@ \class{MimeWriter} instances have the following methods: -\begin{methoddesc}{addheader}{key, value\optional{, prefix}} +\begin{methoddesc}[MimeWriter]{addheader}{key, value\optional{, prefix}} Add a header line to the MIME message. The \var{key} is the name of the header, where the \var{value} obviously provides the value of the header. The optional argument \var{prefix} determines where the header @@ -39,14 +39,14 @@ the start. The default is to append. \end{methoddesc} -\begin{methoddesc}{flushheaders}{} +\begin{methoddesc}[MimeWriter]{flushheaders}{} Causes all headers accumulated so far to be written out (and forgotten). This is useful if you don't need a body part at all, e.g.\ for a subpart of type \mimetype{message/rfc822} that's (mis)used to store some header-like information. \end{methoddesc} -\begin{methoddesc}{startbody}{ctype\optional{, plist\optional{, prefix}}} +\begin{methoddesc}[MimeWriter]{startbody}{ctype\optional{, plist\optional{, prefix}}} Returns a file-like object which can be used to write to the body of the message. The content-type is set to the provided \var{ctype}, and the optional parameter \var{plist} provides @@ -55,8 +55,8 @@ insert at the start. \end{methoddesc} -\begin{methoddesc}{startmultipartbody}{subtype\optional{, - boundary\optional{, plist\optional{, prefix}}}} +\begin{methoddesc}[MimeWriter]{startmultipartbody}{subtype\optional{, + boundary\optional{, plist\optional{, prefix}}}} Returns a file-like object which can be used to write to the body of the message. Additionally, this method initializes the multi-part code, where \var{subtype} provides the multipart subtype, @@ -66,7 +66,7 @@ created using \method{nextpart()}. \end{methoddesc} -\begin{methoddesc}{nextpart}{} +\begin{methoddesc}[MimeWriter]{nextpart}{} Returns a new instance of \class{MimeWriter} which represents an individual part in a multipart message. This may be used to write the part as well as used for creating recursively complex multipart @@ -74,7 +74,7 @@ \method{startmultipartbody()} before using \method{nextpart()}. \end{methoddesc} -\begin{methoddesc}{lastpart}{} +\begin{methoddesc}[MimeWriter]{lastpart}{} This is used to designate the last part of a multipart message, and should \emph{always} be used when writing multipart messages. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libmmap.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libmmap.tex (original) +++ python/branches/p3yk/Doc/lib/libmmap.tex Fri Apr 27 21:54:29 2007 @@ -89,18 +89,18 @@ Memory-mapped file objects support the following methods: -\begin{methoddesc}{close}{} +\begin{methoddesc}[mmap]{close}{} Close the file. Subsequent calls to other methods of the object will result in an exception being raised. \end{methoddesc} -\begin{methoddesc}{find}{string\optional{, start}} +\begin{methoddesc}[mmap]{find}{string\optional{, start}} Returns the lowest index in the object where the substring \var{string} is found. Returns \code{-1} on failure. \var{start} is the index at which the search begins, and defaults to zero. \end{methoddesc} -\begin{methoddesc}{flush}{\optional{offset, size}} +\begin{methoddesc}[mmap]{flush}{\optional{offset, size}} Flushes changes made to the in-memory copy of a file back to disk. Without use of this call there is no guarantee that changes are written back before the object is destroyed. If \var{offset} and @@ -109,36 +109,36 @@ is flushed. \end{methoddesc} -\begin{methoddesc}{move}{\var{dest}, \var{src}, \var{count}} +\begin{methoddesc}[mmap]{move}{\var{dest}, \var{src}, \var{count}} Copy the \var{count} bytes starting at offset \var{src} to the destination index \var{dest}. If the mmap was created with \constant{ACCESS_READ}, then calls to move will throw a \exception{TypeError} exception. \end{methoddesc} -\begin{methoddesc}{read}{\var{num}} +\begin{methoddesc}[mmap]{read}{\var{num}} Return a string containing up to \var{num} bytes starting from the current file position; the file position is updated to point after the bytes that were returned. \end{methoddesc} -\begin{methoddesc}{read_byte}{} +\begin{methoddesc}[mmap]{read_byte}{} Returns a string of length 1 containing the character at the current file position, and advances the file position by 1. \end{methoddesc} -\begin{methoddesc}{readline}{} +\begin{methoddesc}[mmap]{readline}{} Returns a single line, starting at the current file position and up to the next newline. \end{methoddesc} -\begin{methoddesc}{resize}{\var{newsize}} +\begin{methoddesc}[mmap]{resize}{\var{newsize}} Resizes the map and the underlying file, if any. If the mmap was created with \constant{ACCESS_READ} or \constant{ACCESS_COPY}, resizing the map will throw a \exception{TypeError} exception. \end{methoddesc} -\begin{methoddesc}{seek}{pos\optional{, whence}} +\begin{methoddesc}[mmap]{seek}{pos\optional{, whence}} Set the file's current position. \var{whence} argument is optional and defaults to \code{os.SEEK_SET} or \code{0} (absolute file positioning); other values are \code{os.SEEK_CUR} or \code{1} (seek @@ -146,16 +146,16 @@ (seek relative to the file's end). \end{methoddesc} -\begin{methoddesc}{size}{} +\begin{methoddesc}[mmap]{size}{} Return the length of the file, which can be larger than the size of the memory-mapped area. \end{methoddesc} -\begin{methoddesc}{tell}{} +\begin{methoddesc}[mmap]{tell}{} Returns the current position of the file pointer. \end{methoddesc} -\begin{methoddesc}{write}{\var{string}} +\begin{methoddesc}[mmap]{write}{\var{string}} Write the bytes in \var{string} into memory at the current position of the file pointer; the file position is updated to point after the bytes that were written. If the mmap was created with @@ -163,7 +163,7 @@ \exception{TypeError} exception. \end{methoddesc} -\begin{methoddesc}{write_byte}{\var{byte}} +\begin{methoddesc}[mmap]{write_byte}{\var{byte}} Write the single-character string \var{byte} into memory at the current position of the file pointer; the file position is advanced by \code{1}. If the mmap was created with \constant{ACCESS_READ}, Modified: python/branches/p3yk/Doc/lib/libmsilib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libmsilib.tex (original) +++ python/branches/p3yk/Doc/lib/libmsilib.tex Fri Apr 27 21:54:29 2007 @@ -121,17 +121,17 @@ \subsection{Database Objects\label{database-objects}} -\begin{methoddesc}{OpenView}{sql} +\begin{methoddesc}[Database]{OpenView}{sql} Return a view object, by calling \cfunction{MSIDatabaseOpenView}. \var{sql} is the SQL statement to execute. \end{methoddesc} -\begin{methoddesc}{Commit}{} +\begin{methoddesc}[Database]{Commit}{} Commit the changes pending in the current transaction, by calling \cfunction{MSIDatabaseCommit}. \end{methoddesc} -\begin{methoddesc}{GetSummaryInformation}{count} +\begin{methoddesc}[Database]{GetSummaryInformation}{count} Return a new summary information object, by calling \cfunction{MsiGetSummaryInformation}. \var{count} is the maximum number of updated values. @@ -145,24 +145,24 @@ \subsection{View Objects\label{view-objects}} -\begin{methoddesc}{Execute}{\optional{params=None}} +\begin{methoddesc}[View]{Execute}{\optional{params=None}} Execute the SQL query of the view, through \cfunction{MSIViewExecute}. \var{params} is an optional record describing actual values of the parameter tokens in the query. \end{methoddesc} -\begin{methoddesc}{GetColumnInfo}{kind} +\begin{methoddesc}[View]{GetColumnInfo}{kind} Return a record describing the columns of the view, through calling \cfunction{MsiViewGetColumnInfo}. \var{kind} can be either \code{MSICOLINFO_NAMES} or \code{MSICOLINFO_TYPES}. \end{methoddesc} -\begin{methoddesc}{Fetch}{} +\begin{methoddesc}[View]{Fetch}{} Return a result record of the query, through calling \cfunction{MsiViewFetch}. \end{methoddesc} -\begin{methoddesc}{Modify}{kind, data} +\begin{methoddesc}[View]{Modify}{kind, data} Modify the view, by calling \cfunction{MsiViewModify}. \var{kind} can be one of \code{MSIMODIFY_SEEK}, \code{MSIMODIFY_REFRESH}, \code{MSIMODIFY_INSERT}, \code{MSIMODIFY_UPDATE}, \code{MSIMODIFY_ASSIGN}, @@ -174,7 +174,7 @@ \var{data} must be a record describing the new data. \end{methoddesc} -\begin{methoddesc}{Close}{} +\begin{methoddesc}[View]{Close}{} Close the view, through \cfunction{MsiViewClose}. \end{methoddesc} @@ -188,7 +188,7 @@ \subsection{Summary Information Objects\label{summary-objects}} -\begin{methoddesc}{GetProperty}{field} +\begin{methoddesc}[SummaryInformation]{GetProperty}{field} Return a property of the summary, through \cfunction{MsiSummaryInfoGetProperty}. \var{field} is the name of the property, and can be one of the constants @@ -200,19 +200,19 @@ \code{PID_APPNAME}, or \code{PID_SECURITY}. \end{methoddesc} -\begin{methoddesc}{GetPropertyCount}{} +\begin{methoddesc}[SummaryInformation]{GetPropertyCount}{} Return the number of summary properties, through \cfunction{MsiSummaryInfoGetPropertyCount}. \end{methoddesc} -\begin{methoddesc}{SetProperty}{field, value} +\begin{methoddesc}[SummaryInformation]{SetProperty}{field, value} Set a property through \cfunction{MsiSummaryInfoSetProperty}. \var{field} can have the same values as in \method{GetProperty}, \var{value} is the new value of the property. Possible value types are integer and string. \end{methoddesc} -\begin{methoddesc}{Persist}{} +\begin{methoddesc}[SummaryInformation]{Persist}{} Write the modified properties to the summary information stream, using \cfunction{MsiSummaryInfoPersist}. \end{methoddesc} @@ -226,27 +226,27 @@ \subsection{Record Objects\label{record-objects}} -\begin{methoddesc}{GetFieldCount}{} +\begin{methoddesc}[Record]{GetFieldCount}{} Return the number of fields of the record, through \cfunction{MsiRecordGetFieldCount}. \end{methoddesc} -\begin{methoddesc}{SetString}{field, value} +\begin{methoddesc}[Record]{SetString}{field, value} Set \var{field} to \var{value} through \cfunction{MsiRecordSetString}. \var{field} must be an integer; \var{value} a string. \end{methoddesc} -\begin{methoddesc}{SetStream}{field, value} +\begin{methoddesc}[Record]{SetStream}{field, value} Set \var{field} to the contents of the file named \var{value}, through \cfunction{MsiRecordSetStream}. \var{field} must be an integer; \var{value} a string. \end{methoddesc} -\begin{methoddesc}{SetInteger}{field, value} +\begin{methoddesc}[Record]{SetInteger}{field, value} Set \var{field} to \var{value} through \cfunction{MsiRecordSetInteger}. Both \var{field} and \var{value} must be an integer. \end{methoddesc} -\begin{methoddesc}{ClearData}{} +\begin{methoddesc}[Record]{ClearData}{} Set all fields of the record to 0, through \cfunction{MsiRecordClearData}. \end{methoddesc} @@ -274,7 +274,7 @@ \var{name} is the name of the CAB file in the MSI file. \end{classdesc} -\begin{methoddesc}[CAB]{append}{full, logical} +\begin{methoddesc}[CAB]{append}{full, file, logical} Add the file with the pathname \var{full} to the CAB file, under the name \var{logical}. If there is already a file named \var{logical}, a new file name is created. @@ -283,7 +283,7 @@ new name of the file inside the CAB file. \end{methoddesc} -\begin{methoddesc}[CAB]{append}{database} +\begin{methoddesc}[CAB]{commit}{database} Generate a CAB file, add it as a stream to the MSI file, put it into the \code{Media} table, and remove the generated file from the disk. Modified: python/branches/p3yk/Doc/lib/libmultifile.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libmultifile.tex (original) +++ python/branches/p3yk/Doc/lib/libmultifile.tex Fri Apr 27 21:54:29 2007 @@ -48,7 +48,7 @@ A \class{MultiFile} instance has the following methods: -\begin{methoddesc}{readline}{str} +\begin{methoddesc}[MultiFile]{readline}{str} Read a line. If the line is data (not a section-divider or end-marker or real EOF) return it. If the line matches the most-recently-stacked boundary, return \code{''} and set \code{self.last} to 1 or 0 according as @@ -58,33 +58,33 @@ all boundaries have been popped. \end{methoddesc} -\begin{methoddesc}{readlines}{str} +\begin{methoddesc}[MultiFile]{readlines}{str} Return all lines remaining in this part as a list of strings. \end{methoddesc} -\begin{methoddesc}{read}{} +\begin{methoddesc}[MultiFile]{read}{} Read all lines, up to the next section. Return them as a single (multiline) string. Note that this doesn't take a size argument! \end{methoddesc} -\begin{methoddesc}{seek}{pos\optional{, whence}} +\begin{methoddesc}[MultiFile]{seek}{pos\optional{, whence}} Seek. Seek indices are relative to the start of the current section. The \var{pos} and \var{whence} arguments are interpreted as for a file seek. \end{methoddesc} -\begin{methoddesc}{tell}{} +\begin{methoddesc}[MultiFile]{tell}{} Return the file position relative to the start of the current section. \end{methoddesc} -\begin{methoddesc}{next}{} +\begin{methoddesc}[MultiFile]{next}{} Skip lines to the next section (that is, read lines until a section-divider or end-marker has been consumed). Return true if there is such a section, false if an end-marker is seen. Re-enable the most-recently-pushed boundary. \end{methoddesc} -\begin{methoddesc}{is_data}{str} +\begin{methoddesc}[MultiFile]{is_data}{str} Return true if \var{str} is data and false if it might be a section boundary. As written, it tests for a prefix other than \code{'-}\code{-'} at start of line (which all MIME boundaries have) but it is declared so @@ -95,7 +95,7 @@ processing, not cause it to fail. \end{methoddesc} -\begin{methoddesc}{push}{str} +\begin{methoddesc}[MultiFile]{push}{str} Push a boundary string. When a decorated version of this boundary is found as an input line, it will be interpreted as a section-divider or end-marker (depending on the decoration, see \rfc{2045}). All subsequent @@ -108,12 +108,12 @@ boundary will raise an error. \end{methoddesc} -\begin{methoddesc}{pop}{} +\begin{methoddesc}[MultiFile]{pop}{} Pop a section boundary. This boundary will no longer be interpreted as EOF. \end{methoddesc} -\begin{methoddesc}{section_divider}{str} +\begin{methoddesc}[MultiFile]{section_divider}{str} Turn a boundary into a section-divider line. By default, this method prepends \code{'-}\code{-'} (which MIME section boundaries have) but it is declared so it can be overridden in derived classes. This @@ -121,7 +121,7 @@ ignores trailing whitespace. \end{methoddesc} -\begin{methoddesc}{end_marker}{str} +\begin{methoddesc}[MultiFile]{end_marker}{str} Turn a boundary string into an end-marker line. By default, this method prepends \code{'-}\code{-'} and appends \code{'-}\code{-'} (like a MIME-multipart end-of-message marker) but it is declared so it can be @@ -131,11 +131,11 @@ Finally, \class{MultiFile} instances have two public instance variables: -\begin{memberdesc}{level} +\begin{memberdesc}[MultiFile]{level} Nesting depth of the current part. \end{memberdesc} -\begin{memberdesc}{last} +\begin{memberdesc}[MultiFile]{last} True if the last end-of-file was for an end-of-message marker. \end{memberdesc} Modified: python/branches/p3yk/Doc/lib/libmutex.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libmutex.tex (original) +++ python/branches/p3yk/Doc/lib/libmutex.tex Fri Apr 27 21:54:29 2007 @@ -35,23 +35,23 @@ \class{mutex} objects have following methods: -\begin{methoddesc}{test}{} +\begin{methoddesc}[mutex]{test}{} Check whether the mutex is locked. \end{methoddesc} -\begin{methoddesc}{testandset}{} +\begin{methoddesc}[mutex]{testandset}{} ``Atomic'' test-and-set, grab the lock if it is not set, and return \code{True}, otherwise, return \code{False}. \end{methoddesc} -\begin{methoddesc}{lock}{function, argument} +\begin{methoddesc}[mutex]{lock}{function, argument} Execute \code{\var{function}(\var{argument})}, unless the mutex is locked. In the case it is locked, place the function and argument on the queue. See \method{unlock} for explanation of when \code{\var{function}(\var{argument})} is executed in that case. \end{methoddesc} -\begin{methoddesc}{unlock}{} +\begin{methoddesc}[mutex]{unlock}{} Unlock the mutex if queue is empty, otherwise execute the first element in the queue. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libnetrc.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libnetrc.tex (original) +++ python/branches/p3yk/Doc/lib/libnetrc.tex Fri Apr 27 21:54:29 2007 @@ -35,7 +35,7 @@ A \class{netrc} instance has the following methods: -\begin{methoddesc}{authenticators}{host} +\begin{methoddesc}[netrc]{authenticators}{host} Return a 3-tuple \code{(\var{login}, \var{account}, \var{password})} of authenticators for \var{host}. If the netrc file did not contain an entry for the given host, return the tuple associated with @@ -43,20 +43,20 @@ available, return \code{None}. \end{methoddesc} -\begin{methoddesc}{__repr__}{} +\begin{methoddesc}[netrc]{__repr__}{} Dump the class data as a string in the format of a netrc file. (This discards comments and may reorder the entries.) \end{methoddesc} Instances of \class{netrc} have public instance variables: -\begin{memberdesc}{hosts} +\begin{memberdesc}[netrc]{hosts} Dictionary mapping host names to \code{(\var{login}, \var{account}, \var{password})} tuples. The `default' entry, if any, is represented as a pseudo-host by that name. \end{memberdesc} -\begin{memberdesc}{macros} +\begin{memberdesc}[netrc]{macros} Dictionary mapping macro names to string lists. \end{memberdesc} Modified: python/branches/p3yk/Doc/lib/libnntplib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libnntplib.tex (original) +++ python/branches/p3yk/Doc/lib/libnntplib.tex Fri Apr 27 21:54:29 2007 @@ -121,13 +121,13 @@ the above exceptions. -\begin{methoddesc}{getwelcome}{} +\begin{methoddesc}[NNTP]{getwelcome}{} Return the welcome message sent by the server in reply to the initial connection. (This message sometimes contains disclaimers or help information that may be relevant to the user.) \end{methoddesc} -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[NNTP]{set_debuglevel}{level} Set the instance's debugging level. This controls the amount of debugging output printed. The default, \code{0}, produces no debugging output. A value of \code{1} produces a moderate amount of debugging @@ -137,7 +137,7 @@ message text). \end{methoddesc} -\begin{methoddesc}{newgroups}{date, time, \optional{file}} +\begin{methoddesc}[NNTP]{newgroups}{date, time, \optional{file}} Send a \samp{NEWGROUPS} command. The \var{date} argument should be a string of the form \code{'\var{yy}\var{mm}\var{dd}'} indicating the date, and \var{time} should be a string of the form @@ -152,7 +152,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{newnews}{group, date, time, \optional{file}} +\begin{methoddesc}[NNTP]{newnews}{group, date, time, \optional{file}} Send a \samp{NEWNEWS} command. Here, \var{group} is a group name or \code{'*'}, and \var{date} and \var{time} have the same meaning as for \method{newgroups()}. Return a pair \code{(\var{response}, @@ -165,7 +165,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{list}{\optional{file}} +\begin{methoddesc}[NNTP]{list}{\optional{file}} Send a \samp{LIST} command. Return a pair \code{(\var{response}, \var{list})} where \var{list} is a list of tuples. Each tuple has the form \code{(\var{group}, \var{last}, \var{first}, \var{flag})}, where @@ -182,7 +182,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{descriptions}{grouppattern} +\begin{methoddesc}[NNTP]{descriptions}{grouppattern} Send a \samp{LIST NEWSGROUPS} command, where \var{grouppattern} is a wildmat string as specified in RFC2980 (it's essentially the same as DOS or UNIX shell wildcard strings). Return a pair \code{(\var{response}, @@ -192,7 +192,7 @@ \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{description}{group} +\begin{methoddesc}[NNTP]{description}{group} Get a description for a single group \var{group}. If more than one group matches (if 'group' is a real wildmat string), return the first match. If no group matches, return an empty string. @@ -203,7 +203,7 @@ \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}{group}{name} +\begin{methoddesc}[NNTP]{group}{name} Send a \samp{GROUP} command, where \var{name} is the group name. Return a tuple \code{(\var{response}, \var{count}, \var{first}, \var{last}, \var{name})} where \var{count} is the (estimated) number @@ -212,7 +212,7 @@ \var{name} is the group name. The numbers are returned as strings. \end{methoddesc} -\begin{methoddesc}{help}{\optional{file}} +\begin{methoddesc}[NNTP]{help}{\optional{file}} Send a \samp{HELP} command. Return a pair \code{(\var{response}, \var{list})} where \var{list} is a list of help strings. If the \var{file} parameter is supplied, then the output of the @@ -223,7 +223,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{stat}{id} +\begin{methoddesc}[NNTP]{stat}{id} Send a \samp{STAT} command, where \var{id} is the message id (enclosed in \character{<} and \character{>}) or an article number (as a string). Return a triple \code{(\var{response}, \var{number}, \var{id})} where @@ -231,15 +231,15 @@ message id (enclosed in \character{<} and \character{>}). \end{methoddesc} -\begin{methoddesc}{next}{} +\begin{methoddesc}[NNTP]{next}{} Send a \samp{NEXT} command. Return as for \method{stat()}. \end{methoddesc} -\begin{methoddesc}{last}{} +\begin{methoddesc}[NNTP]{last}{} Send a \samp{LAST} command. Return as for \method{stat()}. \end{methoddesc} -\begin{methoddesc}{head}{id} +\begin{methoddesc}[NNTP]{head}{id} Send a \samp{HEAD} command, where \var{id} has the same meaning as for \method{stat()}. Return a tuple \code{(\var{response}, \var{number}, \var{id}, \var{list})} @@ -248,7 +248,7 @@ list of lines, without trailing newlines). \end{methoddesc} -\begin{methoddesc}{body}{id,\optional{file}} +\begin{methoddesc}[NNTP]{body}{id,\optional{file}} Send a \samp{BODY} command, where \var{id} has the same meaning as for \method{stat()}. If the \var{file} parameter is supplied, then the body is stored in a file. If \var{file} is a string, then @@ -259,16 +259,16 @@ the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{article}{id} +\begin{methoddesc}[NNTP]{article}{id} Send an \samp{ARTICLE} command, where \var{id} has the same meaning as for \method{stat()}. Return as for \method{head()}. \end{methoddesc} -\begin{methoddesc}{slave}{} +\begin{methoddesc}[NNTP]{slave}{} Send a \samp{SLAVE} command. Return the server's \var{response}. \end{methoddesc} -\begin{methoddesc}{xhdr}{header, string, \optional{file}} +\begin{methoddesc}[NNTP]{xhdr}{header, string, \optional{file}} Send an \samp{XHDR} command. This command is not defined in the RFC but is a common extension. The \var{header} argument is a header keyword, e.g. \code{'subject'}. The \var{string} argument should have @@ -286,7 +286,7 @@ If \var{file} is supplied, then the returned \var{list} is an empty list. \end{methoddesc} -\begin{methoddesc}{post}{file} +\begin{methoddesc}[NNTP]{post}{file} Post an article using the \samp{POST} command. The \var{file} argument is an open file object which is read until EOF using its \method{readline()} method. It should be a well-formed news article, @@ -294,14 +294,14 @@ automatically escapes lines beginning with \samp{.}. \end{methoddesc} -\begin{methoddesc}{ihave}{id, file} +\begin{methoddesc}[NNTP]{ihave}{id, file} Send an \samp{IHAVE} command. \var{id} is a message id (enclosed in \character{<} and \character{>}). If the response is not an error, treat \var{file} exactly as for the \method{post()} method. \end{methoddesc} -\begin{methoddesc}{date}{} +\begin{methoddesc}[NNTP]{date}{} Return a triple \code{(\var{response}, \var{date}, \var{time})}, containing the current date and time in a form suitable for the \method{newnews()} and \method{newgroups()} methods. @@ -309,7 +309,7 @@ servers. \end{methoddesc} -\begin{methoddesc}{xgtitle}{name, \optional{file}} +\begin{methoddesc}[NNTP]{xgtitle}{name, \optional{file}} Process an \samp{XGTITLE} command, returning a pair \code{(\var{response}, \var{list})}, where \var{list} is a list of tuples containing \code{(\var{name}, \var{title})}. @@ -327,7 +327,7 @@ \method{descriptions()} or \method{description()} instead. \end{methoddesc} -\begin{methoddesc}{xover}{start, end, \optional{file}} +\begin{methoddesc}[NNTP]{xover}{start, end, \optional{file}} Return a pair \code{(\var{resp}, \var{list})}. \var{list} is a list of tuples, one for each article in the range delimited by the \var{start} and \var{end} article numbers. Each tuple is of the form @@ -343,13 +343,13 @@ servers. \end{methoddesc} -\begin{methoddesc}{xpath}{id} +\begin{methoddesc}[NNTP]{xpath}{id} Return a pair \code{(\var{resp}, \var{path})}, where \var{path} is the directory path to the article with message ID \var{id}. This is an optional NNTP extension, and may not be supported by all servers. \end{methoddesc} -\begin{methoddesc}{quit}{} +\begin{methoddesc}[NNTP]{quit}{} Send a \samp{QUIT} command and close the connection. Once this method has been called, no other methods of the NNTP object should be called. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/liboptparse.tex ============================================================================== --- python/branches/p3yk/Doc/lib/liboptparse.tex (original) +++ python/branches/p3yk/Doc/lib/liboptparse.tex Fri Apr 27 21:54:29 2007 @@ -518,7 +518,7 @@ is then printed before the detailed option help. If you don't supply a usage string, \module{optparse} uses a bland but sensible -default: ``\code{usage: {\%}prog {[}options]"}, which is fine if your script +default: \code{"usage: {\%}prog {[}options]"}, which is fine if your script doesn't take any positional arguments. \item {} Modified: python/branches/p3yk/Doc/lib/libos.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libos.tex (original) +++ python/branches/p3yk/Doc/lib/libos.tex Fri Apr 27 21:54:29 2007 @@ -1233,7 +1233,8 @@ \end{funcdesc} \begin{funcdesc}{walk}{top\optional{, topdown\code{=True} - \optional{, onerror\code{=None}}}} + \optional{, onerror\code{=None}\optional{, + followlinks\code{=False}}}}} \index{directory!walking} \index{directory!traversal} \function{walk()} generates the file names in a directory tree, by @@ -1273,6 +1274,18 @@ to abort the walk. Note that the filename is available as the \code{filename} attribute of the exception object. +By default, \function{walk()} will not walk down into symbolic links that +resolve to directories. Set \var{followlinks} to True to visit directories +pointed to by symlinks, on systems that support them. + +\versionadded[The \var{followlinks} parameter]{2.6} + +\begin{notice} +Be aware that setting \var{followlinks} to true can lead to infinite recursion +if a link points to a parent directory of itself. \function{walk()} does not +keep track of the directories it visited already. +\end{notice} + \begin{notice} If you pass a relative pathname, don't change the current working directory between resumptions of \function{walk()}. \function{walk()} @@ -1280,15 +1293,6 @@ doesn't either. \end{notice} -\begin{notice} -On systems that support symbolic links, links to subdirectories appear -in \var{dirnames} lists, but \function{walk()} will not visit them -(infinite loops are hard to avoid when following symbolic links). -To visit linked directories, you can identify them with -\code{os.path.islink(\var{path})}, and invoke \code{walk(\var{path})} -on each directly. -\end{notice} - This example displays the number of bytes taken by non-directory files in each directory under the starting directory, except that it doesn't look under any CVS subdirectory: Modified: python/branches/p3yk/Doc/lib/libpdb.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libpdb.tex (original) +++ python/branches/p3yk/Doc/lib/libpdb.tex Fri Apr 27 21:54:29 2007 @@ -378,6 +378,14 @@ (Pdb) \end{verbatim} +\item[run \optional{\var{args} ...}] +Restart the debugged python program. If an argument is supplied, it is +splitted with "shlex" and the result is used as the new sys.argv. +History, breakpoints, actions and debugger options are preserved. +"restart" is an alias for "run". + +\versionadded{2.6} + \item[q(uit)] Quit from the debugger. Modified: python/branches/p3yk/Doc/lib/libpipes.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libpipes.tex (original) +++ python/branches/p3yk/Doc/lib/libpipes.tex Fri Apr 27 21:54:29 2007 @@ -39,21 +39,21 @@ Template objects following methods: -\begin{methoddesc}{reset}{} +\begin{methoddesc}[Template]{reset}{} Restore a pipeline template to its initial state. \end{methoddesc} -\begin{methoddesc}{clone}{} +\begin{methoddesc}[Template]{clone}{} Return a new, equivalent, pipeline template. \end{methoddesc} -\begin{methoddesc}{debug}{flag} +\begin{methoddesc}[Template]{debug}{flag} If \var{flag} is true, turn debugging on. Otherwise, turn debugging off. When debugging is on, commands to be executed are printed, and the shell is given \code{set -x} command to be more verbose. \end{methoddesc} -\begin{methoddesc}{append}{cmd, kind} +\begin{methoddesc}[Template]{append}{cmd, kind} Append a new action at the end. The \var{cmd} variable must be a valid bourne shell command. The \var{kind} variable consists of two letters. @@ -68,17 +68,17 @@ the command does not write anything, and hence must be last.) \end{methoddesc} -\begin{methoddesc}{prepend}{cmd, kind} +\begin{methoddesc}[Template]{prepend}{cmd, kind} Add a new action at the beginning. See \method{append()} for explanations of the arguments. \end{methoddesc} -\begin{methoddesc}{open}{file, mode} +\begin{methoddesc}[Template]{open}{file, mode} Return a file-like object, open to \var{file}, but read from or written to by the pipeline. Note that only one of \code{'r'}, \code{'w'} may be given. \end{methoddesc} -\begin{methoddesc}{copy}{infile, outfile} +\begin{methoddesc}[Template]{copy}{infile, outfile} Copy \var{infile} to \var{outfile} through the pipe. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libplatform.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libplatform.tex (original) +++ python/branches/p3yk/Doc/lib/libplatform.tex Fri Apr 27 21:54:29 2007 @@ -80,6 +80,22 @@ Returns a string identifying the compiler used for compiling Python. \end{funcdesc} +\begin{funcdesc}{python_branch}{} + Returns a string identifying the Python implementation SCM branch. + \versionadded{2.6} +\end{funcdesc} + +\begin{funcdesc}{python_implementation}{} + Returns a string identifying the Python implementation. + Possible return values are: 'CPython', 'IronPython', 'Jython' + \versionadded{2.6} +\end{funcdesc} + +\begin{funcdesc}{python_revision}{} + Returns a string identifying the Python implementation SCM revision. + \versionadded{2.6} +\end{funcdesc} + \begin{funcdesc}{python_version}{} Returns the Python version as string \code{'major.minor.patchlevel'} @@ -205,6 +221,7 @@ which defaults to the args given as parameters. \end{funcdesc} +% Document linux_distribution()? \begin{funcdesc}{libc_ver}{executable=sys.executable, lib='', version='', chunksize=2048} Modified: python/branches/p3yk/Doc/lib/libpopen2.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libpopen2.tex (original) +++ python/branches/p3yk/Doc/lib/libpopen2.tex Fri Apr 27 21:54:29 2007 @@ -2,7 +2,6 @@ Subprocesses with accessible I/O streams} \declaremodule{standard}{popen2} - \platform{Unix, Windows} \modulesynopsis{Subprocesses with accessible standard I/O streams.} \sectionauthor{Drew Csillag}{drew_csillag at geocities.com} @@ -85,12 +84,12 @@ Instances of the \class{Popen3} and \class{Popen4} classes have the following methods: -\begin{methoddesc}{poll}{} +\begin{methoddesc}[Popen3]{poll}{} Returns \code{-1} if child process hasn't completed yet, or its return code otherwise. \end{methoddesc} -\begin{methoddesc}{wait}{} +\begin{methoddesc}[Popen3]{wait}{} Waits for and returns the status code of the child process. The status code encodes both the return code of the process and information about whether it exited using the \cfunction{exit()} @@ -102,24 +101,24 @@ The following attributes are also available: -\begin{memberdesc}{fromchild} +\begin{memberdesc}[Popen3]{fromchild} A file object that provides output from the child process. For \class{Popen4} instances, this will provide both the standard output and standard error streams. \end{memberdesc} -\begin{memberdesc}{tochild} +\begin{memberdesc}[Popen3]{tochild} A file object that provides input to the child process. \end{memberdesc} -\begin{memberdesc}{childerr} +\begin{memberdesc}[Popen3]{childerr} A file object that provides error output from the child process, if \var{capturestderr} was true for the constructor, otherwise \code{None}. This will always be \code{None} for \class{Popen4} instances. \end{memberdesc} -\begin{memberdesc}{pid} +\begin{memberdesc}[Popen3]{pid} The process ID of the child process. \end{memberdesc} Modified: python/branches/p3yk/Doc/lib/libpoplib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libpoplib.tex (original) +++ python/branches/p3yk/Doc/lib/libpoplib.tex Fri Apr 27 21:54:29 2007 @@ -23,15 +23,18 @@ Note that POP3, though widely supported, is obsolescent. The implementation quality of POP3 servers varies widely, and too many are quite poor. If your mailserver supports IMAP, you would be better off -using the \code{\refmodule{imaplib}.\class{IMAP4}} class, as IMAP +using the \class{\refmodule{imaplib}.IMAP4} class, as IMAP servers tend to be better implemented. A single class is provided by the \module{poplib} module: -\begin{classdesc}{POP3}{host\optional{, port}} +\begin{classdesc}{POP3}{host\optional{, port\optional{, timeout}}} This class implements the actual POP3 protocol. The connection is created when the instance is initialized. If \var{port} is omitted, the standard POP3 port (110) is used. +The optional \var{timeout} parameter specifies a timeout in seconds for the +connection attempt (if not specified, or passed as None, the global default +timeout setting will be used). \end{classdesc} \begin{classdesc}{POP3_SSL}{host\optional{, port\optional{, keyfile\optional{, certfile}}}} @@ -47,8 +50,9 @@ One exception is defined as an attribute of the \module{poplib} module: \begin{excdesc}{error_proto} -Exception raised on any errors. The reason for the exception is -passed to the constructor as a string. +Exception raised on any errors from this module (errors from +\module{socket} module are not caught). The reason for the exception +is passed to the constructor as a string. \end{excdesc} \begin{seealso} @@ -70,7 +74,7 @@ An \class{POP3} instance has the following methods: -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[POP3]{set_debuglevel}{level} Set the instance's debugging level. This controls the amount of debugging output printed. The default, \code{0}, produces no debugging output. A value of \code{1} produces a moderate amount of @@ -79,64 +83,64 @@ logging each line sent and received on the control connection. \end{methoddesc} -\begin{methoddesc}{getwelcome}{} +\begin{methoddesc}[POP3]{getwelcome}{} Returns the greeting string sent by the POP3 server. \end{methoddesc} -\begin{methoddesc}{user}{username} +\begin{methoddesc}[POP3]{user}{username} Send user command, response should indicate that a password is required. \end{methoddesc} -\begin{methoddesc}{pass_}{password} +\begin{methoddesc}[POP3]{pass_}{password} Send password, response includes message count and mailbox size. Note: the mailbox on the server is locked until \method{quit()} is called. \end{methoddesc} -\begin{methoddesc}{apop}{user, secret} +\begin{methoddesc}[POP3]{apop}{user, secret} Use the more secure APOP authentication to log into the POP3 server. \end{methoddesc} -\begin{methoddesc}{rpop}{user} +\begin{methoddesc}[POP3]{rpop}{user} Use RPOP authentication (similar to UNIX r-commands) to log into POP3 server. \end{methoddesc} -\begin{methoddesc}{stat}{} +\begin{methoddesc}[POP3]{stat}{} Get mailbox status. The result is a tuple of 2 integers: \code{(\var{message count}, \var{mailbox size})}. \end{methoddesc} -\begin{methoddesc}{list}{\optional{which}} +\begin{methoddesc}[POP3]{list}{\optional{which}} Request message list, result is in the form \code{(\var{response}, ['mesg_num octets', ...], \var{octets})}. If \var{which} is set, it is the message to list. \end{methoddesc} -\begin{methoddesc}{retr}{which} +\begin{methoddesc}[POP3]{retr}{which} Retrieve whole message number \var{which}, and set its seen flag. Result is in form \code{(\var{response}, ['line', ...], \var{octets})}. \end{methoddesc} -\begin{methoddesc}{dele}{which} +\begin{methoddesc}[POP3]{dele}{which} Flag message number \var{which} for deletion. On most servers deletions are not actually performed until QUIT (the major exception is Eudora QPOP, which deliberately violates the RFCs by doing pending deletes on any disconnect). \end{methoddesc} -\begin{methoddesc}{rset}{} +\begin{methoddesc}[POP3]{rset}{} Remove any deletion marks for the mailbox. \end{methoddesc} -\begin{methoddesc}{noop}{} +\begin{methoddesc}[POP3]{noop}{} Do nothing. Might be used as a keep-alive. \end{methoddesc} -\begin{methoddesc}{quit}{} +\begin{methoddesc}[POP3]{quit}{} Signoff: commit changes, unlock mailbox, drop connection. \end{methoddesc} -\begin{methoddesc}{top}{which, howmuch} +\begin{methoddesc}[POP3]{top}{which, howmuch} Retrieves the message header plus \var{howmuch} lines of the message after the header of message number \var{which}. Result is in form \code{(\var{response}, ['line', ...], \var{octets})}. @@ -148,7 +152,7 @@ trusting it. \end{methoddesc} -\begin{methoddesc}{uidl}{\optional{which}} +\begin{methoddesc}[POP3]{uidl}{\optional{which}} Return message digest (unique id) list. If \var{which} is specified, result contains the unique id for that message in the form \code{'\var{response}\ \var{mesgnum}\ \var{uid}}, Modified: python/branches/p3yk/Doc/lib/libposixfile.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libposixfile.tex (original) +++ python/branches/p3yk/Doc/lib/libposixfile.tex Fri Apr 27 21:54:29 2007 @@ -62,8 +62,7 @@ The posixfile object defines the following additional methods: -\setindexsubitem{(posixfile method)} -\begin{funcdesc}{lock}{fmt, \optional{len\optional{, start\optional{, whence}}}} +\begin{methoddesc}[posixfile]{lock}{fmt, \optional{len\optional{, start\optional{, whence}}}} Lock the specified section of the file that the file object is referring to. The format is explained below in a table. The \var{len} argument specifies the length of the @@ -74,9 +73,9 @@ \constant{SEEK_CUR} or \constant{SEEK_END}. The default is \constant{SEEK_SET}. For more information about the arguments refer to the \manpage{fcntl}{2} manual page on your system. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{flags}{\optional{flags}} +\begin{methoddesc}[posixfile]{flags}{\optional{flags}} Set the specified flags for the file that the file object is referring to. The new flags are ORed with the old flags, unless specified otherwise. The format is explained below in a table. Without @@ -84,25 +83,25 @@ a string indicating the current flags is returned (this is the same as the \samp{?} modifier). For more information about the flags refer to the \manpage{fcntl}{2} manual page on your system. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{dup}{} +\begin{methoddesc}[posixfile]{dup}{} Duplicate the file object and the underlying file pointer and file descriptor. The resulting object behaves as if it were newly opened. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{dup2}{fd} +\begin{methoddesc}[posixfile]{dup2}{fd} Duplicate the file object and the underlying file pointer and file descriptor. The new object will have the given file descriptor. Otherwise the resulting object behaves as if it were newly opened. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{file}{} +\begin{methoddesc}[posixfile]{file}{} Return the standard file object that the posixfile object is based on. This is sometimes necessary for functions that insist on a standard file object. -\end{funcdesc} +\end{methoddesc} All methods raise \exception{IOError} when the request fails. Modified: python/branches/p3yk/Doc/lib/libposixpath.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libposixpath.tex (original) +++ python/branches/p3yk/Doc/lib/libposixpath.tex Fri Apr 27 21:54:29 2007 @@ -58,18 +58,20 @@ \end{funcdesc} \begin{funcdesc}{expanduser}{path} -On \UNIX, return the argument with an initial component of \samp{\~} or -\samp{\~\var{user}} replaced by that \var{user}'s home directory. -An initial \samp{\~} is replaced by the environment variable +On \UNIX{} and Windows, return the argument with an initial component of +\samp{\~} or \samp{\~\var{user}} replaced by that \var{user}'s home directory. + +On \UNIX, an initial \samp{\~} is replaced by the environment variable \envvar{HOME} if it is set; otherwise the current user's home directory is looked up in the password directory through the built-in module \refmodule{pwd}\refbimodindex{pwd}. An initial \samp{\~\var{user}} is looked up directly in the password directory. -On Windows, only \samp{\~} is supported; it is replaced by the -environment variable \envvar{HOME} or by a combination of -\envvar{HOMEDRIVE} and \envvar{HOMEPATH}. +On Windows, \envvar{HOME} and \envvar{USERPROFILE} will be used if set, +otherwise a combination of \envvar{HOMEPATH} and \envvar{HOMEDRIVE} will be +used. An initial \samp{\~\var{user}} is handled by stripping the last +directory component from the created user path derived above. If the expansion fails or if the path does not begin with a tilde, the path is returned unchanged. @@ -81,6 +83,9 @@ replaced by the value of environment variable \var{name}. Malformed variable names and references to non-existing variables are left unchanged. + +On Windows, \samp{\%\var{name}\%} expansions are supported in addition to +\samp{\$\var{name}} and \samp{\$\{\var{name}\}}. \end{funcdesc} \begin{funcdesc}{getatime}{path} @@ -184,6 +189,15 @@ \versionadded{2.2} \end{funcdesc} +\begin{funcdesc}{relpath}{path\optional{, start}} +Return a relative filepath to \var{path} either from the current +directory or from an optional \var{start} point. + +\var{start} defaults to \member{os.curdir}. +Availability: Windows, \UNIX. +\versionadded{2.6} +\end{funcdesc} + \begin{funcdesc}{samefile}{path1, path2} Return \code{True} if both pathname arguments refer to the same file or directory (as indicated by device number and i-node number). @@ -234,7 +248,12 @@ Split the pathname \var{path} into a pair \code{(\var{root}, \var{ext})} such that \code{\var{root} + \var{ext} == \var{path}}, and \var{ext} is empty or begins with a period and contains -at most one period. +at most one period. Leading periods on the basename are +ignored; \code{\var{splitext}.('.cshrc')} returns +\code{('.cshrc', '')}. + +\versionchanged[Earlier versions could produce an empty root when +the only period was the first character]{2.6} \end{funcdesc} \begin{funcdesc}{splitunc}{path} Modified: python/branches/p3yk/Doc/lib/libpprint.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libpprint.tex (original) +++ python/branches/p3yk/Doc/lib/libpprint.tex Fri Apr 27 21:54:29 2007 @@ -158,12 +158,12 @@ \class{PrettyPrinter} instances have the following methods: -\begin{methoddesc}{pformat}{object} +\begin{methoddesc}[PrettyPrinter]{pformat}{object} Return the formatted representation of \var{object}. This takes into account the options passed to the \class{PrettyPrinter} constructor. \end{methoddesc} -\begin{methoddesc}{pprint}{object} +\begin{methoddesc}[PrettyPrinter]{pprint}{object} Print the formatted representation of \var{object} on the configured stream, followed by a newline. \end{methoddesc} @@ -173,7 +173,7 @@ instance is slightly more efficient since new \class{PrettyPrinter} objects don't need to be created. -\begin{methoddesc}{isreadable}{object} +\begin{methoddesc}[PrettyPrinter]{isreadable}{object} Determine if the formatted representation of the object is ``readable,'' or can be used to reconstruct the value using \function{eval()}\bifuncindex{eval}. Note that this returns false for @@ -182,7 +182,7 @@ this returns false. \end{methoddesc} -\begin{methoddesc}{isrecursive}{object} +\begin{methoddesc}[PrettyPrinter]{isrecursive}{object} Determine if the object requires a recursive representation. \end{methoddesc} @@ -190,7 +190,7 @@ way objects are converted to strings. The default implementation uses the internals of the \function{saferepr()} implementation. -\begin{methoddesc}{format}{object, context, maxlevels, level} +\begin{methoddesc}[PrettyPrinter]{format}{object, context, maxlevels, level} Returns three values: the formatted version of \var{object} as a string, a flag indicating whether the result is readable, and a flag indicating whether recursion was detected. The first argument is the Modified: python/branches/p3yk/Doc/lib/libqueue.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libqueue.tex (original) +++ python/branches/p3yk/Doc/lib/libqueue.tex Fri Apr 27 21:54:29 2007 @@ -45,22 +45,22 @@ is not described here. See the source code for details. The public methods are: -\begin{methoddesc}{qsize}{} +\begin{methoddesc}[Queue]{qsize}{} Return the approximate size of the queue. Because of multithreading semantics, this number is not reliable. \end{methoddesc} -\begin{methoddesc}{empty}{} +\begin{methoddesc}[Queue]{empty}{} Return \code{True} if the queue is empty, \code{False} otherwise. Because of multithreading semantics, this is not reliable. \end{methoddesc} -\begin{methoddesc}{full}{} +\begin{methoddesc}[Queue]{full}{} Return \code{True} if the queue is full, \code{False} otherwise. Because of multithreading semantics, this is not reliable. \end{methoddesc} -\begin{methoddesc}{put}{item\optional{, block\optional{, timeout}}} +\begin{methoddesc}[Queue]{put}{item\optional{, block\optional{, timeout}}} Put \var{item} into the queue. If optional args \var{block} is true and \var{timeout} is None (the default), block if necessary until a free slot is available. If \var{timeout} is a positive number, it @@ -74,11 +74,11 @@ \end{methoddesc} -\begin{methoddesc}{put_nowait}{item} +\begin{methoddesc}[Queue]{put_nowait}{item} Equivalent to \code{put(\var{item}, False)}. \end{methoddesc} -\begin{methoddesc}{get}{\optional{block\optional{, timeout}}} +\begin{methoddesc}[Queue]{get}{\optional{block\optional{, timeout}}} Remove and return an item from the queue. If optional args \var{block} is true and \var{timeout} is None (the default), block if necessary until an item is available. If \var{timeout} is @@ -92,14 +92,14 @@ \end{methoddesc} -\begin{methoddesc}{get_nowait}{} +\begin{methoddesc}[Queue]{get_nowait}{} Equivalent to \code{get(False)}. \end{methoddesc} Two methods are offered to support tracking whether enqueued tasks have been fully processed by daemon consumer threads. -\begin{methoddesc}{task_done}{} +\begin{methoddesc}[Queue]{task_done}{} Indicate that a formerly enqueued task is complete. Used by queue consumer threads. For each \method{get()} used to fetch a task, a subsequent call to \method{task_done()} tells the queue that the processing on the task is complete. @@ -113,7 +113,7 @@ \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}{join}{} +\begin{methoddesc}[Queue]{join}{} Blocks until all items in the queue have been gotten and processed. The count of unfinished tasks goes up whenever an item is added to the Modified: python/branches/p3yk/Doc/lib/libre.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libre.tex (original) +++ python/branches/p3yk/Doc/lib/libre.tex Fri Apr 27 21:54:29 2007 @@ -812,7 +812,7 @@ \end{methoddesc} \begin{methoddesc}[MatchObject]{start}{\optional{group}} -\methodline{end}{\optional{group}} +\methodline[MatchObject]{end}{\optional{group}} Return the indices of the start and end of the substring matched by \var{group}; \var{group} defaults to zero (meaning the whole matched substring). Modified: python/branches/p3yk/Doc/lib/librepr.tex ============================================================================== --- python/branches/p3yk/Doc/lib/librepr.tex (original) +++ python/branches/p3yk/Doc/lib/librepr.tex Fri Apr 27 21:54:29 2007 @@ -44,18 +44,18 @@ and methods which format specific object types. -\begin{memberdesc}{maxlevel} +\begin{memberdesc}[Repr]{maxlevel} Depth limit on the creation of recursive representations. The default is \code{6}. \end{memberdesc} -\begin{memberdesc}{maxdict} -\memberline{maxlist} -\memberline{maxtuple} -\memberline{maxset} -\memberline{maxfrozenset} -\memberline{maxdeque} -\memberline{maxarray} +\begin{memberdesc}[Repr]{maxdict} +\memberline[Repr]{maxlist} +\memberline[Repr]{maxtuple} +\memberline[Repr]{maxset} +\memberline[Repr]{maxfrozenset} +\memberline[Repr]{maxdeque} +\memberline[Repr]{maxarray} Limits on the number of entries represented for the named object type. The default is \code{4} for \member{maxdict}, \code{5} for \member{maxarray}, and \code{6} for the others. @@ -63,13 +63,13 @@ and \member{set}]{2.4}. \end{memberdesc} -\begin{memberdesc}{maxlong} +\begin{memberdesc}[Repr]{maxlong} Maximum number of characters in the representation for a long integer. Digits are dropped from the middle. The default is \code{40}. \end{memberdesc} -\begin{memberdesc}{maxstring} +\begin{memberdesc}[Repr]{maxstring} Limit on the number of characters in the representation of the string. Note that the ``normal'' representation of the string is used as the character source: if escape sequences are needed in the @@ -77,19 +77,19 @@ shortened. The default is \code{30}. \end{memberdesc} -\begin{memberdesc}{maxother} +\begin{memberdesc}[Repr]{maxother} This limit is used to control the size of object types for which no specific formatting method is available on the \class{Repr} object. It is applied in a similar manner as \member{maxstring}. The default is \code{20}. \end{memberdesc} -\begin{methoddesc}{repr}{obj} +\begin{methoddesc}[Repr]{repr}{obj} The equivalent to the built-in \function{repr()} that uses the formatting imposed by the instance. \end{methoddesc} -\begin{methoddesc}{repr1}{obj, level} +\begin{methoddesc}[Repr]{repr1}{obj, level} Recursive implementation used by \method{repr()}. This uses the type of \var{obj} to determine which formatting method to call, passing it \var{obj} and \var{level}. The type-specific methods @@ -98,7 +98,7 @@ call. \end{methoddesc} -\begin{methoddescni}{repr_\var{type}}{obj, level} +\begin{methoddescni}[Repr]{repr_\var{type}}{obj, level} Formatting methods for specific types are implemented as methods with a name based on the type name. In the method name, \var{type} is replaced by Modified: python/branches/p3yk/Doc/lib/librexec.tex ============================================================================== --- python/branches/p3yk/Doc/lib/librexec.tex (original) +++ python/branches/p3yk/Doc/lib/librexec.tex Fri Apr 27 21:54:29 2007 @@ -89,20 +89,20 @@ \class{RExec} instances support the following methods: -\begin{methoddesc}{r_eval}{code} +\begin{methoddesc}[RExec]{r_eval}{code} \var{code} must either be a string containing a Python expression, or a compiled code object, which will be evaluated in the restricted environment's \module{__main__} module. The value of the expression or code object will be returned. \end{methoddesc} -\begin{methoddesc}{r_exec}{code} +\begin{methoddesc}[RExec]{r_exec}{code} \var{code} must either be a string containing one or more lines of Python code, or a compiled code object, which will be executed in the restricted environment's \module{__main__} module. \end{methoddesc} -\begin{methoddesc}{r_execfile}{filename} +\begin{methoddesc}[RExec]{r_execfile}{filename} Execute the Python code contained in the file \var{filename} in the restricted environment's \module{__main__} module. \end{methoddesc} @@ -112,17 +112,17 @@ restricted versions of the standard I/O streams \code{sys.stdin}, \code{sys.stderr}, and \code{sys.stdout}. -\begin{methoddesc}{s_eval}{code} +\begin{methoddesc}[RExec]{s_eval}{code} \var{code} must be a string containing a Python expression, which will be evaluated in the restricted environment. \end{methoddesc} -\begin{methoddesc}{s_exec}{code} +\begin{methoddesc}[RExec]{s_exec}{code} \var{code} must be a string containing one or more lines of Python code, which will be executed in the restricted environment. \end{methoddesc} -\begin{methoddesc}{s_execfile}{code} +\begin{methoddesc}[RExec]{s_execfile}{code} Execute the Python code contained in the file \var{filename} in the restricted environment. \end{methoddesc} @@ -132,13 +132,13 @@ Overriding these methods in a subclass is used to change the policies enforced by a restricted environment. -\begin{methoddesc}{r_import}{modulename\optional{, globals\optional{, - locals\optional{, fromlist}}}} +\begin{methoddesc}[RExec]{r_import}{modulename\optional{, globals\optional{, + locals\optional{, fromlist}}}} Import the module \var{modulename}, raising an \exception{ImportError} exception if the module is considered unsafe. \end{methoddesc} -\begin{methoddesc}{r_open}{filename\optional{, mode\optional{, bufsize}}} +\begin{methoddesc}[RExec]{r_open}{filename\optional{, mode\optional{, bufsize}}} Method called when \function{open()} is called in the restricted environment. The arguments are identical to those of \function{open()}, and a file object (or a class instance compatible with file objects) @@ -148,28 +148,28 @@ \method{r_open()}. \end{methoddesc} -\begin{methoddesc}{r_reload}{module} +\begin{methoddesc}[RExec]{r_reload}{module} Reload the module object \var{module}, re-parsing and re-initializing it. \end{methoddesc} -\begin{methoddesc}{r_unload}{module} +\begin{methoddesc}[RExec]{r_unload}{module} Unload the module object \var{module} (remove it from the restricted environment's \code{sys.modules} dictionary). \end{methoddesc} And their equivalents with access to restricted standard I/O streams: -\begin{methoddesc}{s_import}{modulename\optional{, globals\optional{, - locals\optional{, fromlist}}}} +\begin{methoddesc}[RExec]{s_import}{modulename\optional{, globals\optional{, + locals\optional{, fromlist}}}} Import the module \var{modulename}, raising an \exception{ImportError} exception if the module is considered unsafe. \end{methoddesc} -\begin{methoddesc}{s_reload}{module} +\begin{methoddesc}[RExec]{s_reload}{module} Reload the module object \var{module}, re-parsing and re-initializing it. \end{methoddesc} -\begin{methoddesc}{s_unload}{module} +\begin{methoddesc}[RExec]{s_unload}{module} Unload the module object \var{module}. % XXX what are the semantics of this? \end{methoddesc} @@ -184,7 +184,7 @@ Instances of the new class will then use those new values. All these attributes are tuples of strings. -\begin{memberdesc}{nok_builtin_names} +\begin{memberdesc}[RExec]{nok_builtin_names} Contains the names of built-in functions which will \emph{not} be available to programs running in the restricted environment. The value for \class{RExec} is \code{('open', 'reload', '__import__')}. @@ -196,7 +196,7 @@ this module.) \end{memberdesc} -\begin{memberdesc}{ok_builtin_modules} +\begin{memberdesc}[RExec]{ok_builtin_modules} Contains the names of built-in modules which can be safely imported. The value for \class{RExec} is \code{('audioop', 'array', 'binascii', 'cmath', 'errno', 'imageop', 'marshal', 'math', 'md5', 'operator', @@ -205,14 +205,14 @@ applies --- use the value from the base class as a starting point. \end{memberdesc} -\begin{memberdesc}{ok_path} +\begin{memberdesc}[RExec]{ok_path} Contains the directories which will be searched when an \keyword{import} is performed in the restricted environment. The value for \class{RExec} is the same as \code{sys.path} (at the time the module is loaded) for unrestricted code. \end{memberdesc} -\begin{memberdesc}{ok_posix_names} +\begin{memberdesc}[RExec]{ok_posix_names} % Should this be called ok_os_names? Contains the names of the functions in the \refmodule{os} module which will be available to programs running in the restricted environment. The @@ -221,14 +221,14 @@ 'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid')}. \end{memberdesc} -\begin{memberdesc}{ok_sys_names} +\begin{memberdesc}[RExec]{ok_sys_names} Contains the names of the functions and variables in the \refmodule{sys} module which will be available to programs running in the restricted environment. The value for \class{RExec} is \code{('ps1', 'ps2', 'copyright', 'version', 'platform', 'exit', 'maxint')}. \end{memberdesc} -\begin{memberdesc}{ok_file_types} +\begin{memberdesc}[RExec]{ok_file_types} Contains the file types from which modules are allowed to be loaded. Each file type is an integer constant defined in the \refmodule{imp} module. The meaningful values are \constant{PY_SOURCE}, \constant{PY_COMPILED}, and Modified: python/branches/p3yk/Doc/lib/librfc822.tex ============================================================================== --- python/branches/p3yk/Doc/lib/librfc822.tex (original) +++ python/branches/p3yk/Doc/lib/librfc822.tex Fri Apr 27 21:54:29 2007 @@ -100,7 +100,7 @@ \code{'Mon, 20 Nov 1995 19:12:08 -0500'}. If it succeeds in parsing the date, \function{parsedate()} returns a 9-tuple that can be passed directly to \function{time.mktime()}; otherwise \code{None} will be -returned. Note that fields 6, 7, and 8 of the result tuple are not +returned. Note that indexes 6, 7, and 8 of the result tuple are not usable. \end{funcdesc} @@ -114,7 +114,7 @@ variable for the same timezone; the latter variable follows the \POSIX{} standard while this module follows \rfc{2822}.) If the input string has no timezone, the last element of the tuple returned is -\code{None}. Note that fields 6, 7, and 8 of the result tuple are not +\code{None}. Note that indexes 6, 7, and 8 of the result tuple are not usable. \end{funcdesc} @@ -142,12 +142,12 @@ A \class{Message} instance has the following methods: -\begin{methoddesc}{rewindbody}{} +\begin{methoddesc}[Message]{rewindbody}{} Seek to the start of the message body. This only works if the file object is seekable. \end{methoddesc} -\begin{methoddesc}{isheader}{line} +\begin{methoddesc}[Message]{isheader}{line} Returns a line's canonicalized fieldname (the dictionary key that will be used to index it) if the line is a legal \rfc{2822} header; otherwise returns \code{None} (implying that parsing should stop here and the @@ -155,33 +155,33 @@ override this method in a subclass. \end{methoddesc} -\begin{methoddesc}{islast}{line} +\begin{methoddesc}[Message]{islast}{line} Return true if the given line is a delimiter on which Message should stop. The delimiter line is consumed, and the file object's read location positioned immediately after it. By default this method just checks that the line is blank, but you can override it in a subclass. \end{methoddesc} -\begin{methoddesc}{iscomment}{line} +\begin{methoddesc}[Message]{iscomment}{line} Return \code{True} if the given line should be ignored entirely, just skipped. By default this is a stub that always returns \code{False}, but you can override it in a subclass. \end{methoddesc} -\begin{methoddesc}{getallmatchingheaders}{name} +\begin{methoddesc}[Message]{getallmatchingheaders}{name} Return a list of lines consisting of all headers matching \var{name}, if any. Each physical line, whether it is a continuation line or not, is a separate list item. Return the empty list if no header matches \var{name}. \end{methoddesc} -\begin{methoddesc}{getfirstmatchingheader}{name} +\begin{methoddesc}[Message]{getfirstmatchingheader}{name} Return a list of lines comprising the first header matching \var{name}, and its continuation line(s), if any. Return \code{None} if there is no header matching \var{name}. \end{methoddesc} -\begin{methoddesc}{getrawheader}{name} +\begin{methoddesc}[Message]{getrawheader}{name} Return a single string consisting of the text after the colon in the first header matching \var{name}. This includes leading whitespace, the trailing linefeed, and internal linefeeds and whitespace if there @@ -189,19 +189,19 @@ no header matching \var{name}. \end{methoddesc} -\begin{methoddesc}{getheader}{name\optional{, default}} +\begin{methoddesc}[Message]{getheader}{name\optional{, default}} Like \code{getrawheader(\var{name})}, but strip leading and trailing whitespace. Internal whitespace is not stripped. The optional \var{default} argument can be used to specify a different default to be returned when there is no header matching \var{name}. \end{methoddesc} -\begin{methoddesc}{get}{name\optional{, default}} +\begin{methoddesc}[Message]{get}{name\optional{, default}} An alias for \method{getheader()}, to make the interface more compatible with regular dictionaries. \end{methoddesc} -\begin{methoddesc}{getaddr}{name} +\begin{methoddesc}[Message]{getaddr}{name} Return a pair \code{(\var{full name}, \var{email address})} parsed from the string returned by \code{getheader(\var{name})}. If no header matching \var{name} exists, return \code{(None, None)}; @@ -217,7 +217,7 @@ exact same result. \end{methoddesc} -\begin{methoddesc}{getaddrlist}{name} +\begin{methoddesc}[Message]{getaddrlist}{name} This is similar to \code{getaddr(\var{list})}, but parses a header containing a list of email addresses (e.g.\ a \mailheader{To} header) and returns a list of \code{(\var{full name}, \var{email address})} pairs @@ -229,7 +229,7 @@ Any continuation lines the named headers contain are also parsed. \end{methoddesc} -\begin{methoddesc}{getdate}{name} +\begin{methoddesc}[Message]{getdate}{name} Retrieve a header using \method{getheader()} and parse it into a 9-tuple compatible with \function{time.mktime()}; note that fields 6, 7, and 8 are not usable. If there is no header matching @@ -241,7 +241,7 @@ function may occasionally yield an incorrect result. \end{methoddesc} -\begin{methoddesc}{getdate_tz}{name} +\begin{methoddesc}[Message]{getdate_tz}{name} Retrieve a header using \method{getheader()} and parse it into a 10-tuple; the first 9 elements will make a tuple compatible with \function{time.mktime()}, and the 10th is a number giving the offset @@ -270,19 +270,19 @@ Finally, \class{Message} instances have some public instance variables: -\begin{memberdesc}{headers} +\begin{memberdesc}[Message]{headers} A list containing the entire set of header lines, in the order in which they were read (except that setitem calls may disturb this order). Each line contains a trailing newline. The blank line terminating the headers is not contained in the list. \end{memberdesc} -\begin{memberdesc}{fp} +\begin{memberdesc}[Message]{fp} The file or file-like object passed at instantiation time. This can be used to read the message content. \end{memberdesc} -\begin{memberdesc}{unixfrom} +\begin{memberdesc}[Message]{unixfrom} The \UNIX{} \samp{From~} line, if the message had one, or an empty string. This is needed to regenerate the message in some contexts, such as an \code{mbox}-style mailbox file. @@ -293,34 +293,34 @@ An \class{AddressList} instance has the following methods: -\begin{methoddesc}{__len__}{} +\begin{methoddesc}[AddressList]{__len__}{} Return the number of addresses in the address list. \end{methoddesc} -\begin{methoddesc}{__str__}{} +\begin{methoddesc}[AddressList]{__str__}{} Return a canonicalized string representation of the address list. Addresses are rendered in "name" form, comma-separated. \end{methoddesc} -\begin{methoddesc}{__add__}{alist} +\begin{methoddesc}[AddressList]{__add__}{alist} Return a new \class{AddressList} instance that contains all addresses in both \class{AddressList} operands, with duplicates removed (set union). \end{methoddesc} -\begin{methoddesc}{__iadd__}{alist} +\begin{methoddesc}[AddressList]{__iadd__}{alist} In-place version of \method{__add__()}; turns this \class{AddressList} instance into the union of itself and the right-hand instance, \var{alist}. \end{methoddesc} -\begin{methoddesc}{__sub__}{alist} +\begin{methoddesc}[AddressList]{__sub__}{alist} Return a new \class{AddressList} instance that contains every address in the left-hand \class{AddressList} operand that is not present in the right-hand address operand (set difference). \end{methoddesc} -\begin{methoddesc}{__isub__}{alist} +\begin{methoddesc}[AddressList]{__isub__}{alist} In-place version of \method{__sub__()}, removing addresses in this list which are also in \var{alist}. \end{methoddesc} @@ -328,7 +328,7 @@ Finally, \class{AddressList} instances have one public instance variable: -\begin{memberdesc}{addresslist} +\begin{memberdesc}[AddressList]{addresslist} A list of tuple string pairs, one per address. In each member, the first is the canonicalized name part, the second is the actual route-address (\character{@}-separated username-host.domain Modified: python/branches/p3yk/Doc/lib/libsched.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsched.tex (original) +++ python/branches/p3yk/Doc/lib/libsched.tex Fri Apr 27 21:54:29 2007 @@ -48,7 +48,7 @@ \class{scheduler} instances have the following methods: -\begin{methoddesc}{enterabs}{time, priority, action, argument} +\begin{methoddesc}[scheduler]{enterabs}{time, priority, action, argument} Schedule a new event. The \var{time} argument should be a numeric type compatible with the return value of the \var{timefunc} function passed to the constructor. Events scheduled for @@ -63,23 +63,23 @@ the event (see \method{cancel()}). \end{methoddesc} -\begin{methoddesc}{enter}{delay, priority, action, argument} +\begin{methoddesc}[scheduler]{enter}{delay, priority, action, argument} Schedule an event for \var{delay} more time units. Other then the relative time, the other arguments, the effect and the return value are the same as those for \method{enterabs()}. \end{methoddesc} -\begin{methoddesc}{cancel}{event} +\begin{methoddesc}[scheduler]{cancel}{event} Remove the event from the queue. If \var{event} is not an event currently in the queue, this method will raise a \exception{RuntimeError}. \end{methoddesc} -\begin{methoddesc}{empty}{} +\begin{methoddesc}[scheduler]{empty}{} Return true if the event queue is empty. \end{methoddesc} -\begin{methoddesc}{run}{} +\begin{methoddesc}[scheduler]{run}{} Run all scheduled events. This function will wait (using the \function{delayfunc} function passed to the constructor) for the next event, then execute it and so on until there are no more Modified: python/branches/p3yk/Doc/lib/libselect.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libselect.tex (original) +++ python/branches/p3yk/Doc/lib/libselect.tex Fri Apr 27 21:54:29 2007 @@ -77,7 +77,7 @@ \cfunction{select()} is O(highest file descriptor), while \cfunction{poll()} is O(number of file descriptors). -\begin{methoddesc}{register}{fd\optional{, eventmask}} +\begin{methoddesc}[poll]{register}{fd\optional{, eventmask}} Register a file descriptor with the polling object. Future calls to the \method{poll()} method will then check whether the file descriptor has any pending I/O events. \var{fd} can be either an integer, or an @@ -105,7 +105,7 @@ once. \end{methoddesc} -\begin{methoddesc}{unregister}{fd} +\begin{methoddesc}[poll]{unregister}{fd} Remove a file descriptor being tracked by a polling object. Just like the \method{register()} method, \var{fd} can be an integer or an object with a \method{fileno()} method that returns an integer. @@ -114,7 +114,7 @@ causes a \exception{KeyError} exception to be raised. \end{methoddesc} -\begin{methoddesc}{poll}{\optional{timeout}} +\begin{methoddesc}[poll]{poll}{\optional{timeout}} Polls the set of registered file descriptors, and returns a possibly-empty list containing \code{(\var{fd}, \var{event})} 2-tuples for the descriptors that have events or errors to report. Modified: python/branches/p3yk/Doc/lib/libshlex.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libshlex.tex (original) +++ python/branches/p3yk/Doc/lib/libshlex.tex Fri Apr 27 21:54:29 2007 @@ -58,7 +58,7 @@ A \class{shlex} instance has the following methods: -\begin{methoddesc}{get_token}{} +\begin{methoddesc}[shlex]{get_token}{} Return a token. If tokens have been stacked using \method{push_token()}, pop a token off the stack. Otherwise, read one from the input stream. If reading encounters an immediate @@ -66,17 +66,17 @@ in non-\POSIX{} mode, and \code{None} in \POSIX{} mode). \end{methoddesc} -\begin{methoddesc}{push_token}{str} +\begin{methoddesc}[shlex]{push_token}{str} Push the argument onto the token stack. \end{methoddesc} -\begin{methoddesc}{read_token}{} +\begin{methoddesc}[shlex]{read_token}{} Read a raw token. Ignore the pushback stack, and do not interpret source requests. (This is not ordinarily a useful entry point, and is documented here only for the sake of completeness.) \end{methoddesc} -\begin{methoddesc}{sourcehook}{filename} +\begin{methoddesc}[shlex]{sourcehook}{filename} When \class{shlex} detects a source request (see \member{source} below) this method is given the following token as argument, and expected to return a tuple consisting of a filename and @@ -106,7 +106,7 @@ \method{push_source()} and \method{pop_source()} methods. \end{methoddesc} -\begin{methoddesc}{push_source}{stream\optional{, filename}} +\begin{methoddesc}[shlex]{push_source}{stream\optional{, filename}} Push an input source stream onto the input stack. If the filename argument is specified it will later be available for use in error messages. This is the same method used internally by the @@ -114,14 +114,14 @@ \versionadded{2.1} \end{methoddesc} -\begin{methoddesc}{pop_source}{} +\begin{methoddesc}[shlex]{pop_source}{} Pop the last-pushed input source from the input stack. This is the same method used internally when the lexer reaches \EOF{} on a stacked input stream. \versionadded{2.1} \end{methoddesc} -\begin{methoddesc}{error_leader}{\optional{file\optional{, line}}} +\begin{methoddesc}[shlex]{error_leader}{\optional{file\optional{, line}}} This method generates an error message leader in the format of a \UNIX{} C compiler error label; the format is \code{'"\%s", line \%d: '}, where the \samp{\%s} is replaced with the name of the current source @@ -137,63 +137,63 @@ variables which either control lexical analysis or can be used for debugging: -\begin{memberdesc}{commenters} +\begin{memberdesc}[shlex]{commenters} The string of characters that are recognized as comment beginners. All characters from the comment beginner to end of line are ignored. Includes just \character{\#} by default. \end{memberdesc} -\begin{memberdesc}{wordchars} +\begin{memberdesc}[shlex]{wordchars} The string of characters that will accumulate into multi-character tokens. By default, includes all \ASCII{} alphanumerics and underscore. \end{memberdesc} -\begin{memberdesc}{whitespace} +\begin{memberdesc}[shlex]{whitespace} Characters that will be considered whitespace and skipped. Whitespace bounds tokens. By default, includes space, tab, linefeed and carriage-return. \end{memberdesc} -\begin{memberdesc}{escape} +\begin{memberdesc}[shlex]{escape} Characters that will be considered as escape. This will be only used in \POSIX{} mode, and includes just \character{\textbackslash} by default. \versionadded{2.3} \end{memberdesc} -\begin{memberdesc}{quotes} +\begin{memberdesc}[shlex]{quotes} Characters that will be considered string quotes. The token accumulates until the same quote is encountered again (thus, different quote types protect each other as in the shell.) By default, includes \ASCII{} single and double quotes. \end{memberdesc} -\begin{memberdesc}{escapedquotes} +\begin{memberdesc}[shlex]{escapedquotes} Characters in \member{quotes} that will interpret escape characters defined in \member{escape}. This is only used in \POSIX{} mode, and includes just \character{"} by default. \versionadded{2.3} \end{memberdesc} -\begin{memberdesc}{whitespace_split} +\begin{memberdesc}[shlex]{whitespace_split} If \code{True}, tokens will only be split in whitespaces. This is useful, for example, for parsing command lines with \class{shlex}, getting tokens in a similar way to shell arguments. \versionadded{2.3} \end{memberdesc} -\begin{memberdesc}{infile} +\begin{memberdesc}[shlex]{infile} The name of the current input file, as initially set at class instantiation time or stacked by later source requests. It may be useful to examine this when constructing error messages. \end{memberdesc} -\begin{memberdesc}{instream} +\begin{memberdesc}[shlex]{instream} The input stream from which this \class{shlex} instance is reading characters. \end{memberdesc} -\begin{memberdesc}{source} +\begin{memberdesc}[shlex]{source} This member is \code{None} by default. If you assign a string to it, that string will be recognized as a lexical-level inclusion request similar to the \samp{source} keyword in various shells. That is, the @@ -204,23 +204,23 @@ number of levels deep. \end{memberdesc} -\begin{memberdesc}{debug} +\begin{memberdesc}[shlex]{debug} If this member is numeric and \code{1} or more, a \class{shlex} instance will print verbose progress output on its behavior. If you need to use this, you can read the module source code to learn the details. \end{memberdesc} -\begin{memberdesc}{lineno} +\begin{memberdesc}[shlex]{lineno} Source line number (count of newlines seen so far plus one). \end{memberdesc} -\begin{memberdesc}{token} +\begin{memberdesc}[shlex]{token} The token buffer. It may be useful to examine this when catching exceptions. \end{memberdesc} -\begin{memberdesc}{eof} +\begin{memberdesc}[shlex]{eof} Token used to determine end of file. This will be set to the empty string (\code{''}), in non-\POSIX{} mode, and to \code{None} in \POSIX{} mode. Modified: python/branches/p3yk/Doc/lib/libshutil.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libshutil.tex (original) +++ python/branches/p3yk/Doc/lib/libshutil.tex Fri Apr 27 21:54:29 2007 @@ -34,7 +34,9 @@ is the buffer size. In particular, a negative \var{length} value means to copy the data without looping over the source data in chunks; by default the data is read in chunks to avoid uncontrolled - memory consumption. + memory consumption. Note that if the current file position of the + \var{fsrc} object is not 0, only the contents from the current file + position to the end of the file will be copied. \end{funcdesc} \begin{funcdesc}{copymode}{src, dst} Modified: python/branches/p3yk/Doc/lib/libsimplexmlrpc.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsimplexmlrpc.tex (original) +++ python/branches/p3yk/Doc/lib/libsimplexmlrpc.tex Fri Apr 27 21:54:29 2007 @@ -15,7 +15,9 @@ \begin{classdesc}{SimpleXMLRPCServer}{addr\optional{, requestHandler\optional{, - logRequests\optional{, allow_none\optional{, encoding}}}}} + logRequests\optional{, + allow_none\optional{, + encoding}}}}} Create a new server instance. This class provides methods for registration of functions that can be called by @@ -28,8 +30,13 @@ setting this parameter to false will turn off logging. The \var{allow_none} and \var{encoding} parameters are passed on to \module{xmlrpclib} and control the XML-RPC responses that will be returned - from the server. + from the server. The \var{bind_and_activate} parameter controls whether + \method{server_bind()} and \method{server_activate()} are called immediately + by the constructor; it defaults to true. Setting it to false allows code to + manipulate the \var{allow_reuse_address} class variable before the address + is bound. \versionchanged[The \var{allow_none} and \var{encoding} parameters were added]{2.5} + \versionchanged[The \var{bind_and_activate} parameter was added]{2.6} \end{classdesc} \begin{classdesc}{CGIXMLRPCRequestHandler}{\optional{allow_none\optional{, encoding}}} @@ -101,13 +108,13 @@ \end{methoddesc} -\begin{methoddesc}{register_introspection_functions}{} +\begin{methoddesc}[SimpleXMLRPCServer]{register_introspection_functions}{} Registers the XML-RPC introspection functions \code{system.listMethods}, \code{system.methodHelp} and \code{system.methodSignature}. \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{register_multicall_functions}{} +\begin{methoddesc}[SimpleXMLRPCServer]{register_multicall_functions}{} Registers the XML-RPC multicall function system.multicall. \end{methoddesc} @@ -171,7 +178,7 @@ The \class{CGIXMLRPCRequestHandler} class can be used to handle XML-RPC requests sent to Python CGI scripts. -\begin{methoddesc}{register_function}{function\optional{, name}} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{register_function}{function\optional{, name}} Register a function that can respond to XML-RPC requests. If \var{name} is given, it will be the method name associated with function, otherwise \var{function.__name__} will be used. \var{name} @@ -180,7 +187,7 @@ character. \end{methoddesc} -\begin{methoddesc}{register_instance}{instance} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{register_instance}{instance} Register an object which is used to expose method names which have not been registered using \method{register_function()}. If instance contains a \method{_dispatch()} method, it is called with the @@ -196,17 +203,17 @@ back to the client. \end{methoddesc} -\begin{methoddesc}{register_introspection_functions}{} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{register_introspection_functions}{} Register the XML-RPC introspection functions \code{system.listMethods}, \code{system.methodHelp} and \code{system.methodSignature}. \end{methoddesc} -\begin{methoddesc}{register_multicall_functions}{} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{register_multicall_functions}{} Register the XML-RPC multicall function \code{system.multicall}. \end{methoddesc} -\begin{methoddesc}{handle_request}{\optional{request_text = None}} +\begin{methoddesc}[CGIXMLRPCRequestHandler]{handle_request}{\optional{request_text = None}} Handle a XML-RPC request. If \var{request_text} is given, it should be the POST data provided by the HTTP server, otherwise the contents of stdin will be used. Modified: python/branches/p3yk/Doc/lib/libsite.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsite.tex (original) +++ python/branches/p3yk/Doc/lib/libsite.tex Fri Apr 27 21:54:29 2007 @@ -28,12 +28,17 @@ A path configuration file is a file whose name has the form \file{\var{package}.pth} and exists in one of the four directories -mentioned above; its contents are additional items (one -per line) to be added to \code{sys.path}. Non-existing items are -never added to \code{sys.path}, but no check is made that the item -refers to a directory (rather than a file). No item is added to -\code{sys.path} more than once. Blank lines and lines beginning with -\code{\#} are skipped. Lines starting with \code{import} are executed. +mentioned above; its contents are additional items (one per line) to +be added to \code{sys.path}. Non-existing items are never added to +\code{sys.path}, but no check is made that the item refers to a +directory (rather than a file). No item is added to \code{sys.path} +more than once. Blank lines and lines beginning with \code{\#} are +skipped. Lines starting with \code{import} (followed by space or tab) +are executed. + +\versionchanged[A space or tab is now required after the import +keyword]{2.6} + \index{package} \indexiii{path}{configuration}{file} Modified: python/branches/p3yk/Doc/lib/libsmtplib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsmtplib.tex (original) +++ python/branches/p3yk/Doc/lib/libsmtplib.tex Fri Apr 27 21:54:29 2007 @@ -15,13 +15,16 @@ (\citetitle{SMTP Service Extensions}). \begin{classdesc}{SMTP}{\optional{host\optional{, port\optional{, - local_hostname}}}} + local_hostname\optional{, timeout}}}}} A \class{SMTP} instance encapsulates an SMTP connection. It has methods that support a full repertoire of SMTP and ESMTP operations. If the optional host and port parameters are given, the SMTP \method{connect()} method is called with those parameters during initialization. An \exception{SMTPConnectError} is raised if the specified host doesn't respond correctly. +The optional \var{timeout} parameter specifies a timeout in seconds for the +connection attempt (if not specified, or passed as None, the global +default timeout setting will be used). For normal use, you should only require the initialization/connect, \method{sendmail()}, and \method{quit()} methods. An example is @@ -31,7 +34,7 @@ \begin{classdesc}{SMTP_SSL}{\optional{host\optional{, port\optional{, local_hostname\optional{, keyfile\optional{, - certfile}}}}}} + certfile\optional{, timeout}}}}}}} A \class{SMTP_SSL} instance behaves exactly the same as instances of \class{SMTP}. \class{SMTP_SSL} should be used for situations where SSL is required from the beginning of the connection and using \method{starttls()} is not appropriate. @@ -39,6 +42,26 @@ omitted, the standard SMTP-over-SSL port (465) is used. \var{keyfile} and \var{certfile} are also optional, and can contain a PEM formatted private key and certificate chain file for the SSL connection. +The optional \var{timeout} parameter specifies a timeout in seconds for the +connection attempt (if not specified, or passed as None, the global +default timeout setting will be used). +\end{classdesc} + +\begin{classdesc}{LMTP}{\optional{host\optional{, port\optional{, + local_hostname}}}} + +The LMTP protocol, which is very similar to ESMTP, is heavily based +on the standard SMTP client. It's common to use Unix sockets for LMTP, +so our connect() method must support that as well as a regular +host:port server. To specify a Unix socket, you must use an absolute +path for \var{host}, starting with a '/'. + +Authentication is supported, using the regular SMTP mechanism. When +using a Unix socket, LMTP generally don't support or require any +authentication, but your mileage might vary. + +\versionadded{2.6} + \end{classdesc} A nice selection of exceptions is defined as well: @@ -103,13 +126,13 @@ An \class{SMTP} instance has the following methods: -\begin{methoddesc}{set_debuglevel}{level} +\begin{methoddesc}[SMTP]{set_debuglevel}{level} Set the debug output level. A true value for \var{level} results in debug messages for connection and for all messages sent to and received from the server. \end{methoddesc} -\begin{methoddesc}{connect}{\optional{host\optional{, port}}} +\begin{methoddesc}[SMTP]{connect}{\optional{host\optional{, port}}} Connect to a host on a given port. The defaults are to connect to the local host at the standard SMTP port (25). If the hostname ends with a colon (\character{:}) followed by a @@ -119,7 +142,7 @@ host is specified during instantiation. \end{methoddesc} -\begin{methoddesc}{docmd}{cmd, \optional{, argstring}} +\begin{methoddesc}[SMTP]{docmd}{cmd, \optional{, argstring}} Send a command \var{cmd} to the server. The optional argument \var{argstring} is simply concatenated to the command, separated by a space. @@ -136,7 +159,7 @@ \exception{SMTPServerDisconnected} will be raised. \end{methoddesc} -\begin{methoddesc}{helo}{\optional{hostname}} +\begin{methoddesc}[SMTP]{helo}{\optional{hostname}} Identify yourself to the SMTP server using \samp{HELO}. The hostname argument defaults to the fully qualified domain name of the local host. @@ -146,7 +169,7 @@ when necessary. \end{methoddesc} -\begin{methoddesc}{ehlo}{\optional{hostname}} +\begin{methoddesc}[SMTP]{ehlo}{\optional{hostname}} Identify yourself to an ESMTP server using \samp{EHLO}. The hostname argument defaults to the fully qualified domain name of the local host. Examine the response for ESMTP option and store them for use by @@ -157,13 +180,13 @@ will be implicitly called by \method{sendmail()} when necessary. \end{methoddesc} -\begin{methoddesc}{has_extn}{name} +\begin{methoddesc}[SMTP]{has_extn}{name} Return \constant{True} if \var{name} is in the set of SMTP service extensions returned by the server, \constant{False} otherwise. Case is ignored. \end{methoddesc} -\begin{methoddesc}{verify}{address} +\begin{methoddesc}[SMTP]{verify}{address} Check the validity of an address on this server using SMTP \samp{VRFY}. Returns a tuple consisting of code 250 and a full \rfc{822} address (including human name) if the user address is valid. Otherwise returns @@ -172,7 +195,7 @@ \note{Many sites disable SMTP \samp{VRFY} in order to foil spammers.} \end{methoddesc} -\begin{methoddesc}{login}{user, password} +\begin{methoddesc}[SMTP]{login}{user, password} Log in on an SMTP server that requires authentication. The arguments are the username and the password to authenticate with. If there has been no previous \samp{EHLO} or \samp{HELO} command this @@ -190,7 +213,7 @@ \end{description} \end{methoddesc} -\begin{methoddesc}{starttls}{\optional{keyfile\optional{, certfile}}} +\begin{methoddesc}[SMTP]{starttls}{\optional{keyfile\optional{, certfile}}} Put the SMTP connection in TLS (Transport Layer Security) mode. All SMTP commands that follow will be encrypted. You should then call \method{ehlo()} again. @@ -199,8 +222,8 @@ the \refmodule{socket} module's \function{ssl()} function. \end{methoddesc} -\begin{methoddesc}{sendmail}{from_addr, to_addrs, msg\optional{, - mail_options, rcpt_options}} +\begin{methoddesc}[SMTP]{sendmail}{from_addr, to_addrs, msg\optional{, + mail_options, rcpt_options}} Send mail. The required arguments are an \rfc{822} from-address string, a list of \rfc{822} to-address strings (a bare string will be treated as a list with 1 address), and a message string. The caller @@ -256,7 +279,7 @@ \end{methoddesc} -\begin{methoddesc}{quit}{} +\begin{methoddesc}[SMTP]{quit}{} Terminate the SMTP session and close the connection. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libsocket.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsocket.tex (original) +++ python/branches/p3yk/Doc/lib/libsocket.tex Fri Apr 27 21:54:29 2007 @@ -14,7 +14,7 @@ papers: \citetitle{An Introductory 4.3BSD Interprocess Communication Tutorial}, by Stuart Sechrest and \citetitle{An Advanced 4.3BSD Interprocess Communication Tutorial}, by Samuel J. Leffler et al, -both in the \citetitle{\UNIX{} Programmer's Manual, Supplementary Documents 1} +both in the \citetitle{UNIX Programmer's Manual, Supplementary Documents 1} (sections PS1:7 and PS1:8). The platform-specific reference material for the various socket-related system calls are also a valuable source of information on the details of socket semantics. For \UNIX, refer @@ -170,6 +170,15 @@ \versionadded{2.3} \end{datadesc} +\begin{funcdesc}{create_connection}{address\optional{, timeout}} +Connects to the \var{address} received (as usual, a \code{(host, port)} +pair), with an optional timeout for the connection. Specially useful for +higher-level protocols, it is not normally used directly from +application-level code. Passing the optional \var{timeout} parameter +will set the timeout on the socket instance (if it is not given or +\code{None}, the global default timeout setting is used). +\end{funcdesc} + \begin{funcdesc}{getaddrinfo}{host, port\optional{, family\optional{, socktype\optional{, proto\optional{, flags}}}}} @@ -548,7 +557,7 @@ The file object references a \cfunction{dup()}ped version of the socket file descriptor, so the file object and socket object may be closed or garbage-collected independently. -The socket must be in blocking mode. +The socket must be in blocking mode (it can not have a timeout). \index{I/O control!buffering}The optional \var{mode} and \var{bufsize} arguments are interpreted the same way as by the built-in \function{file()} function; see ``Built-in Functions'' @@ -584,6 +593,7 @@ \manpage{recv}{2} for the meaning of the optional argument \var{flags}; it defaults to zero. (The format of \var{address} depends on the address family --- see above.) +\versionadded{2.5} \end{methoddesc} \begin{methoddesc}[socket]{recv_into}{buffer\optional{, nbytes\optional{, flags}}} @@ -593,6 +603,7 @@ receive up to the size available in the given buffer. See the \UNIX{} manual page \manpage{recv}{2} for the meaning of the optional argument \var{flags}; it defaults to zero. +\versionadded{2.5} \end{methoddesc} \begin{methoddesc}[socket]{send}{string\optional{, flags}} @@ -722,23 +733,23 @@ SSL objects have the following methods. -\begin{methoddesc}{write}{s} +\begin{methoddesc}[SSL]{write}{s} Writes the string \var{s} to the on the object's SSL connection. The return value is the number of bytes written. \end{methoddesc} -\begin{methoddesc}{read}{\optional{n}} +\begin{methoddesc}[SSL]{read}{\optional{n}} If \var{n} is provided, read \var{n} bytes from the SSL connection, otherwise read until EOF. The return value is a string of the bytes read. \end{methoddesc} -\begin{methoddesc}{server}{} +\begin{methoddesc}[SSL]{server}{} Returns a string describing the server's certificate. Useful for debugging purposes; do not parse the content of this string because its format can't be parsed unambiguously. \end{methoddesc} -\begin{methoddesc}{issuer}{} +\begin{methoddesc}[SSL]{issuer}{} Returns a string describing the issuer of the server's certificate. Useful for debugging purposes; do not parse the content of this string because its format can't be parsed unambiguously. Modified: python/branches/p3yk/Doc/lib/libsqlite3.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsqlite3.tex (original) +++ python/branches/p3yk/Doc/lib/libsqlite3.tex Fri Apr 27 21:54:29 2007 @@ -210,37 +210,37 @@ A \class{Connection} instance has the following attributes and methods: \label{sqlite3-Connection-IsolationLevel} -\begin{memberdesc}{isolation_level} +\begin{memberdesc}[Connection]{isolation_level} Get or set the current isolation level. None for autocommit mode or one of "DEFERRED", "IMMEDIATE" or "EXLUSIVE". See ``Controlling Transactions'', section~\ref{sqlite3-Controlling-Transactions}, for a more detailed explanation. \end{memberdesc} -\begin{methoddesc}{cursor}{\optional{cursorClass}} +\begin{methoddesc}[Connection]{cursor}{\optional{cursorClass}} The cursor method accepts a single optional parameter \var{cursorClass}. If supplied, this must be a custom cursor class that extends \class{sqlite3.Cursor}. \end{methoddesc} -\begin{methoddesc}{execute}{sql, \optional{parameters}} +\begin{methoddesc}[Connection]{execute}{sql, \optional{parameters}} This is a nonstandard shortcut that creates an intermediate cursor object by calling the cursor method, then calls the cursor's \method{execute} method with the parameters given. \end{methoddesc} -\begin{methoddesc}{executemany}{sql, \optional{parameters}} +\begin{methoddesc}[Connection]{executemany}{sql, \optional{parameters}} This is a nonstandard shortcut that creates an intermediate cursor object by calling the cursor method, then calls the cursor's \method{executemany} method with the parameters given. \end{methoddesc} -\begin{methoddesc}{executescript}{sql_script} +\begin{methoddesc}[Connection]{executescript}{sql_script} This is a nonstandard shortcut that creates an intermediate cursor object by calling the cursor method, then calls the cursor's \method{executescript} method with the parameters given. \end{methoddesc} -\begin{methoddesc}{create_function}{name, num_params, func} +\begin{methoddesc}[Connection]{create_function}{name, num_params, func} Creates a user-defined function that you can later use from within SQL statements under the function name \var{name}. \var{num_params} is the number @@ -255,7 +255,7 @@ \verbatiminput{sqlite3/md5func.py} \end{methoddesc} -\begin{methoddesc}{create_aggregate}{name, num_params, aggregate_class} +\begin{methoddesc}[Connection]{create_aggregate}{name, num_params, aggregate_class} Creates a user-defined aggregate function. @@ -271,7 +271,7 @@ \verbatiminput{sqlite3/mysumaggr.py} \end{methoddesc} -\begin{methoddesc}{create_collation}{name, callable} +\begin{methoddesc}[Connection]{create_collation}{name, callable} Creates a collation with the specified \var{name} and \var{callable}. The callable will be passed two string arguments. It should return -1 if the first @@ -293,14 +293,14 @@ \end{verbatim} \end{methoddesc} -\begin{methoddesc}{interrupt}{} +\begin{methoddesc}[Connection]{interrupt}{} You can call this method from a different thread to abort any queries that might be executing on the connection. The query will then abort and the caller will get an exception. \end{methoddesc} -\begin{methoddesc}{set_authorizer}{authorizer_callback} +\begin{methoddesc}[Connection]{set_authorizer}{authorizer_callback} This routine registers a callback. The callback is invoked for each attempt to access a column of a table in the database. The callback should return @@ -322,7 +322,7 @@ module. \end{methoddesc} -\begin{memberdesc}{row_factory} +\begin{memberdesc}[Connection]{row_factory} You can change this attribute to a callable that accepts the cursor and the original row as a tuple and will return the real result row. This way, you can implement more advanced ways of returning results, such @@ -341,7 +341,7 @@ % XXX what's a db_row-based solution? \end{memberdesc} -\begin{memberdesc}{text_factory} +\begin{memberdesc}[Connection]{text_factory} Using this attribute you can control what objects are returned for the TEXT data type. By default, this attribute is set to \class{unicode} and the \module{sqlite3} module will return Unicode objects for TEXT. If you want to return @@ -359,7 +359,7 @@ \verbatiminput{sqlite3/text_factory.py} \end{memberdesc} -\begin{memberdesc}{total_changes} +\begin{memberdesc}[Connection]{total_changes} Returns the total number of database rows that have been modified, inserted, or deleted since the database connection was opened. \end{memberdesc} @@ -372,7 +372,7 @@ A \class{Cursor} instance has the following attributes and methods: -\begin{methoddesc}{execute}{sql, \optional{parameters}} +\begin{methoddesc}[Cursor]{execute}{sql, \optional{parameters}} Executes a SQL statement. The SQL statement may be parametrized (i. e. placeholders instead of SQL literals). The \module{sqlite3} module supports two kinds of @@ -394,7 +394,7 @@ \end{methoddesc} -\begin{methoddesc}{executemany}{sql, seq_of_parameters} +\begin{methoddesc}[Cursor]{executemany}{sql, seq_of_parameters} Executes a SQL command against all parameter sequences or mappings found in the sequence \var{sql}. The \module{sqlite3} module also allows using an iterator yielding parameters instead of a sequence. @@ -406,7 +406,7 @@ \verbatiminput{sqlite3/executemany_2.py} \end{methoddesc} -\begin{methoddesc}{executescript}{sql_script} +\begin{methoddesc}[Cursor]{executescript}{sql_script} This is a nonstandard convenience method for executing multiple SQL statements at once. It issues a COMMIT statement first, then executes the SQL script it @@ -419,7 +419,7 @@ \verbatiminput{sqlite3/executescript.py} \end{methoddesc} -\begin{memberdesc}{rowcount} +\begin{memberdesc}[Cursor]{rowcount} Although the \class{Cursor} class of the \module{sqlite3} module implements this attribute, the database engine's own support for the determination of "rows affected"/"rows selected" is quirky. Modified: python/branches/p3yk/Doc/lib/libstdtypes.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libstdtypes.tex (original) +++ python/branches/p3yk/Doc/lib/libstdtypes.tex Fri Apr 27 21:54:29 2007 @@ -559,25 +559,25 @@ These are the string methods which both 8-bit strings and Unicode objects support: -\begin{methoddesc}[string]{capitalize}{} +\begin{methoddesc}[str]{capitalize}{} Return a copy of the string with only its first character capitalized. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{center}{width\optional{, fillchar}} +\begin{methoddesc}[str]{center}{width\optional{, fillchar}} Return centered in a string of length \var{width}. Padding is done using the specified \var{fillchar} (default is a space). \versionchanged[Support for the \var{fillchar} argument]{2.4} \end{methoddesc} -\begin{methoddesc}[string]{count}{sub\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{count}{sub\optional{, start\optional{, end}}} Return the number of occurrences of substring \var{sub} in string S\code{[\var{start}:\var{end}]}. Optional arguments \var{start} and \var{end} are interpreted as in slice notation. \end{methoddesc} -\begin{methoddesc}[string]{decode}{\optional{encoding\optional{, errors}}} +\begin{methoddesc}[str]{decode}{\optional{encoding\optional{, errors}}} Decodes the string using the codec registered for \var{encoding}. \var{encoding} defaults to the default string encoding. \var{errors} may be given to set a different error handling scheme. The default is @@ -589,7 +589,7 @@ \versionchanged[Support for other error handling schemes added]{2.3} \end{methoddesc} -\begin{methoddesc}[string]{encode}{\optional{encoding\optional{,errors}}} +\begin{methoddesc}[str]{encode}{\optional{encoding\optional{,errors}}} Return an encoded version of the string. Default encoding is the current default string encoding. \var{errors} may be given to set a different error handling scheme. The default for \var{errors} is @@ -604,7 +604,7 @@ \code{'backslashreplace'} and other error handling schemes added]{2.3} \end{methoddesc} -\begin{methoddesc}[string]{endswith}{suffix\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{endswith}{suffix\optional{, start\optional{, end}}} Return \code{True} if the string ends with the specified \var{suffix}, otherwise return \code{False}. \var{suffix} can also be a tuple of suffixes to look for. With optional \var{start}, test beginning at @@ -613,13 +613,13 @@ \versionchanged[Accept tuples as \var{suffix}]{2.5} \end{methoddesc} -\begin{methoddesc}[string]{expandtabs}{\optional{tabsize}} +\begin{methoddesc}[str]{expandtabs}{\optional{tabsize}} Return a copy of the string where all tab characters are expanded using spaces. If \var{tabsize} is not given, a tab size of \code{8} characters is assumed. \end{methoddesc} -\begin{methoddesc}[string]{find}{sub\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{find}{sub\optional{, start\optional{, end}}} Return the lowest index in the string where substring \var{sub} is found, such that \var{sub} is contained in the range [\var{start}, \var{end}]. Optional arguments \var{start} and \var{end} are @@ -627,47 +627,47 @@ not found. \end{methoddesc} -\begin{methoddesc}[string]{index}{sub\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{index}{sub\optional{, start\optional{, end}}} Like \method{find()}, but raise \exception{ValueError} when the substring is not found. \end{methoddesc} -\begin{methoddesc}[string]{isalnum}{} +\begin{methoddesc}[str]{isalnum}{} Return true if all characters in the string are alphanumeric and there is at least one character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{isalpha}{} +\begin{methoddesc}[str]{isalpha}{} Return true if all characters in the string are alphabetic and there is at least one character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{isdigit}{} +\begin{methoddesc}[str]{isdigit}{} Return true if all characters in the string are digits and there is at least one character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{islower}{} +\begin{methoddesc}[str]{islower}{} Return true if all cased characters in the string are lowercase and there is at least one cased character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{isspace}{} +\begin{methoddesc}[str]{isspace}{} Return true if there are only whitespace characters in the string and there is at least one character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{istitle}{} +\begin{methoddesc}[str]{istitle}{} Return true if the string is a titlecased string and there is at least one character, for example uppercase characters may only follow uncased characters and lowercase characters only cased ones. Return false @@ -676,20 +676,20 @@ For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{isupper}{} +\begin{methoddesc}[str]{isupper}{} Return true if all cased characters in the string are uppercase and there is at least one cased character, false otherwise. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{join}{seq} +\begin{methoddesc}[str]{join}{seq} Return a string which is the concatenation of the strings in the sequence \var{seq}. The separator between elements is the string providing this method. \end{methoddesc} -\begin{methoddesc}[string]{ljust}{width\optional{, fillchar}} +\begin{methoddesc}[str]{ljust}{width\optional{, fillchar}} Return the string left justified in a string of length \var{width}. Padding is done using the specified \var{fillchar} (default is a space). The original string is returned if @@ -697,13 +697,13 @@ \versionchanged[Support for the \var{fillchar} argument]{2.4} \end{methoddesc} -\begin{methoddesc}[string]{lower}{} +\begin{methoddesc}[str]{lower}{} Return a copy of the string converted to lowercase. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{lstrip}{\optional{chars}} +\begin{methoddesc}[str]{lstrip}{\optional{chars}} Return a copy of the string with leading characters removed. The \var{chars} argument is a string specifying the set of characters to be removed. If omitted or \code{None}, the \var{chars} argument @@ -718,7 +718,7 @@ \versionchanged[Support for the \var{chars} argument]{2.2.2} \end{methoddesc} -\begin{methoddesc}[string]{partition}{sep} +\begin{methoddesc}[str]{partition}{sep} Split the string at the first occurrence of \var{sep}, and return a 3-tuple containing the part before the separator, the separator itself, and the part after the separator. If the separator is not @@ -727,26 +727,26 @@ \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}[string]{replace}{old, new\optional{, count}} +\begin{methoddesc}[str]{replace}{old, new\optional{, count}} Return a copy of the string with all occurrences of substring \var{old} replaced by \var{new}. If the optional argument \var{count} is given, only the first \var{count} occurrences are replaced. \end{methoddesc} -\begin{methoddesc}[string]{rfind}{sub \optional{,start \optional{,end}}} +\begin{methoddesc}[str]{rfind}{sub \optional{,start \optional{,end}}} Return the highest index in the string where substring \var{sub} is found, such that \var{sub} is contained within s[start,end]. Optional arguments \var{start} and \var{end} are interpreted as in slice notation. Return \code{-1} on failure. \end{methoddesc} -\begin{methoddesc}[string]{rindex}{sub\optional{, start\optional{, end}}} +\begin{methoddesc}[str]{rindex}{sub\optional{, start\optional{, end}}} Like \method{rfind()} but raises \exception{ValueError} when the substring \var{sub} is not found. \end{methoddesc} -\begin{methoddesc}[string]{rjust}{width\optional{, fillchar}} +\begin{methoddesc}[str]{rjust}{width\optional{, fillchar}} Return the string right justified in a string of length \var{width}. Padding is done using the specified \var{fillchar} (default is a space). The original string is returned if @@ -754,7 +754,7 @@ \versionchanged[Support for the \var{fillchar} argument]{2.4} \end{methoddesc} -\begin{methoddesc}[string]{rpartition}{sep} +\begin{methoddesc}[str]{rpartition}{sep} Split the string at the last occurrence of \var{sep}, and return a 3-tuple containing the part before the separator, the separator itself, and the part after the separator. If the separator is not @@ -763,7 +763,7 @@ \versionadded{2.5} \end{methoddesc} -\begin{methoddesc}[string]{rsplit}{\optional{sep \optional{,maxsplit}}} +\begin{methoddesc}[str]{rsplit}{\optional{sep \optional{,maxsplit}}} Return a list of the words in the string, using \var{sep} as the delimiter string. If \var{maxsplit} is given, at most \var{maxsplit} splits are done, the \emph{rightmost} ones. If \var{sep} is not specified @@ -773,7 +773,7 @@ \versionadded{2.4} \end{methoddesc} -\begin{methoddesc}[string]{rstrip}{\optional{chars}} +\begin{methoddesc}[str]{rstrip}{\optional{chars}} Return a copy of the string with trailing characters removed. The \var{chars} argument is a string specifying the set of characters to be removed. If omitted or \code{None}, the \var{chars} argument @@ -788,7 +788,7 @@ \versionchanged[Support for the \var{chars} argument]{2.2.2} \end{methoddesc} -\begin{methoddesc}[string]{split}{\optional{sep \optional{,maxsplit}}} +\begin{methoddesc}[str]{split}{\optional{sep \optional{,maxsplit}}} Return a list of the words in the string, using \var{sep} as the delimiter string. If \var{maxsplit} is given, at most \var{maxsplit} splits are done. (thus, the list will have at most \code{\var{maxsplit}+1} @@ -811,13 +811,13 @@ returns an empty list. \end{methoddesc} -\begin{methoddesc}[string]{splitlines}{\optional{keepends}} +\begin{methoddesc}[str]{splitlines}{\optional{keepends}} Return a list of the lines in the string, breaking at line boundaries. Line breaks are not included in the resulting list unless \var{keepends} is given and true. \end{methoddesc} -\begin{methoddesc}[string]{startswith}{prefix\optional{, +\begin{methoddesc}[str]{startswith}{prefix\optional{, start\optional{, end}}} Return \code{True} if string starts with the \var{prefix}, otherwise return \code{False}. \var{prefix} can also be a tuple of @@ -828,7 +828,7 @@ \versionchanged[Accept tuples as \var{prefix}]{2.5} \end{methoddesc} -\begin{methoddesc}[string]{strip}{\optional{chars}} +\begin{methoddesc}[str]{strip}{\optional{chars}} Return a copy of the string with the leading and trailing characters removed. The \var{chars} argument is a string specifying the set of characters to be removed. If omitted or \code{None}, the \var{chars} @@ -843,21 +843,21 @@ \versionchanged[Support for the \var{chars} argument]{2.2.2} \end{methoddesc} -\begin{methoddesc}[string]{swapcase}{} +\begin{methoddesc}[str]{swapcase}{} Return a copy of the string with uppercase characters converted to lowercase and vice versa. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{title}{} +\begin{methoddesc}[str]{title}{} Return a titlecased version of the string: words start with uppercase characters, all remaining cased characters are lowercase. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{translate}{table\optional{, deletechars}} +\begin{methoddesc}[str]{translate}{table\optional{, deletechars}} Return a copy of the string where all characters occurring in the optional argument \var{deletechars} are removed, and the remaining characters have been mapped through the given translation table, which @@ -865,6 +865,13 @@ You can use the \function{maketrans()} helper function in the \refmodule{string} module to create a translation table. +For string objects, set the \var{table} argument to \code{None} +for translations that only delete characters: +\begin{verbatim} + >>> 'read this short text'.translate(None, 'aeiou') + 'rd ths shrt txt' +\end{verbatim} +\versionadded[Support for a \code{None} \var{table} argument]{2.6} For Unicode objects, the \method{translate()} method does not accept the optional \var{deletechars} argument. Instead, it @@ -877,13 +884,13 @@ \module{encodings.cp1251} for an example). \end{methoddesc} -\begin{methoddesc}[string]{upper}{} +\begin{methoddesc}[str]{upper}{} Return a copy of the string converted to uppercase. For 8-bit strings, this method is locale-dependent. \end{methoddesc} -\begin{methoddesc}[string]{zfill}{width} +\begin{methoddesc}[str]{zfill}{width} Return the numeric string left filled with zeros in a string of length \var{width}. The original string is returned if \var{width} is less than \code{len(\var{s})}. @@ -1592,14 +1599,15 @@ iterator, typically in a \keyword{for} loop (for example, \code{for line in f: print line}), the \method{__next__()} method is called repeatedly. This method returns the next input line, or raises -\exception{StopIteration} when \EOF{} is hit. In order to make a -\keyword{for} loop the most efficient way of looping over the lines of -a file (a very common operation), the \method{__next__()} method uses a -hidden read-ahead buffer. As a consequence of using a read-ahead -buffer, combining \method{__next__()} with other file methods (like -\method{readline()}) does not work right. However, using -\method{seek()} to reposition the file to an absolute position will -flush the read-ahead buffer. +\exception{StopIteration} when \EOF{} is hit when the file is open for +reading (behavior is undefined when the file is open for writing). In +order to make a \keyword{for} loop the most efficient way of looping +over the lines of a file (a very common operation), the +\method{__next__()} method uses a hidden read-ahead buffer. As a +consequence of using a read-ahead buffer, combining \method{__next__()} +with other file methods (like \method{readline()}) does not work +right. However, using \method{seek()} to reposition the file to an +absolute position will flush the read-ahead buffer. \versionadded{2.3} \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libstring.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libstring.tex (original) +++ python/branches/p3yk/Doc/lib/libstring.tex Fri Apr 27 21:54:29 2007 @@ -419,7 +419,8 @@ Delete all characters from \var{s} that are in \var{deletechars} (if present), and then translate the characters using \var{table}, which must be a 256-character string giving the translation for each - character value, indexed by its ordinal. + character value, indexed by its ordinal. If \var{table} is \code{None}, + then only the character deletion step is performed. \end{funcdesc} \begin{funcdesc}{upper}{s} Modified: python/branches/p3yk/Doc/lib/libsubprocess.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsubprocess.tex (original) +++ python/branches/p3yk/Doc/lib/libsubprocess.tex Fri Apr 27 21:54:29 2007 @@ -176,16 +176,16 @@ Instances of the \class{Popen} class have the following methods: -\begin{methoddesc}{poll}{} +\begin{methoddesc}[Popen]{poll}{} Check if child process has terminated. Returns returncode attribute. \end{methoddesc} -\begin{methoddesc}{wait}{} +\begin{methoddesc}[Popen]{wait}{} Wait for child process to terminate. Returns returncode attribute. \end{methoddesc} -\begin{methoddesc}{communicate}{input=None} +\begin{methoddesc}[Popen]{communicate}{input=None} Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional \var{input} argument should be a string to be sent to the @@ -199,29 +199,29 @@ The following attributes are also available: -\begin{memberdesc}{stdin} +\begin{memberdesc}[Popen]{stdin} If the \var{stdin} argument is \code{PIPE}, this attribute is a file object that provides input to the child process. Otherwise, it is \code{None}. \end{memberdesc} -\begin{memberdesc}{stdout} +\begin{memberdesc}[Popen]{stdout} If the \var{stdout} argument is \code{PIPE}, this attribute is a file object that provides output from the child process. Otherwise, it is \code{None}. \end{memberdesc} -\begin{memberdesc}{stderr} +\begin{memberdesc}[Popen]{stderr} If the \var{stderr} argument is \code{PIPE}, this attribute is file object that provides error output from the child process. Otherwise, it is \code{None}. \end{memberdesc} -\begin{memberdesc}{pid} +\begin{memberdesc}[Popen]{pid} The process ID of the child process. \end{memberdesc} -\begin{memberdesc}{returncode} +\begin{memberdesc}[Popen]{returncode} The child return code. A \code{None} value indicates that the process hasn't terminated yet. A negative value -N indicates that the child was terminated by signal N (\UNIX{} only). Modified: python/branches/p3yk/Doc/lib/libsun.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsun.tex (original) +++ python/branches/p3yk/Doc/lib/libsun.tex Fri Apr 27 21:54:29 2007 @@ -3,3 +3,5 @@ The modules described in this chapter provide interfaces to features that are unique to SunOS 5 (also known as Solaris version 2). + +\localmoduletable Modified: python/branches/p3yk/Doc/lib/libsys.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsys.tex (original) +++ python/branches/p3yk/Doc/lib/libsys.tex Fri Apr 27 21:54:29 2007 @@ -15,8 +15,8 @@ whether this is a full pathname or not). If the command was executed using the \programopt{-c} command line option to the interpreter, \code{argv[0]} is set to the string \code{'-c'}. If no - script name was passed to the Python interpreter, \code{argv} has - zero length. + script name was passed to the Python interpreter, \code{argv[0]} is + the empty string. \end{datadesc} \begin{datadesc}{byteorder} Modified: python/branches/p3yk/Doc/lib/libtarfile.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libtarfile.tex (original) +++ python/branches/p3yk/Doc/lib/libtarfile.tex Fri Apr 27 21:54:29 2007 @@ -12,21 +12,24 @@ \begin{itemize} \item reads and writes \module{gzip} and \module{bzip2} compressed archives. -\item creates \POSIX{} 1003.1-1990 compliant or GNU tar compatible archives. -\item reads GNU tar extensions \emph{longname}, \emph{longlink} and - \emph{sparse}. -\item stores pathnames of unlimited length using GNU tar extensions. +\item read/write support for the \POSIX{}.1-1988 (ustar) format. +\item read/write support for the GNU tar format including \emph{longname} and + \emph{longlink} extensions, read-only support for the \emph{sparse} + extension. +\item read/write support for the \POSIX{}.1-2001 (pax) format. + \versionadded{2.6} \item handles directories, regular files, hardlinks, symbolic links, fifos, character devices and block devices and is able to acquire and restore file information like timestamp, access permissions and owner. \item can handle tape devices. \end{itemize} -\begin{funcdesc}{open}{\optional{name\optional{, mode - \optional{, fileobj\optional{, bufsize}}}}} +\begin{funcdesc}{open}{name\optional{, mode\optional{, + fileobj\optional{, bufsize}}}, **kwargs} Return a \class{TarFile} object for the pathname \var{name}. - For detailed information on \class{TarFile} objects, - see \citetitle{TarFile Objects} (section \ref{tarfile-objects}). + For detailed information on \class{TarFile} objects and the keyword + arguments that are allowed, see \citetitle{TarFile Objects} + (section \ref{tarfile-objects}). \var{mode} has to be a string of the form \code{'filemode[:compression]'}, it defaults to \code{'r'}. Here is a full list of mode combinations: @@ -130,6 +133,31 @@ \versionadded{2.6} \end{excdesc} +\begin{datadesc}{USTAR_FORMAT} + \POSIX{}.1-1988 (ustar) format. It supports filenames up to a length of + at best 256 characters and linknames up to 100 characters. The maximum + file size is 8 gigabytes. This is an old and limited but widely + supported format. +\end{datadesc} + +\begin{datadesc}{GNU_FORMAT} + GNU tar format. It supports arbitrarily long filenames and linknames and + files bigger than 8 gigabytes. It is the defacto standard on GNU/Linux + systems. +\end{datadesc} + +\begin{datadesc}{PAX_FORMAT} + \POSIX{}.1-2001 (pax) format. It is the most flexible format with + virtually no limits. It supports long filenames and linknames, large files + and stores pathnames in a portable way. However, not all tar + implementations today are able to handle pax archives properly. +\end{datadesc} + +\begin{datadesc}{DEFAULT_FORMAT} + The default format for creating archives. This is currently + \constant{GNU_FORMAT}. +\end{datadesc} + \begin{seealso} \seemodule{zipfile}{Documentation of the \refmodule{zipfile} standard module.} @@ -152,12 +180,21 @@ \class{TarInfo} object, see \citetitle{TarInfo Objects} (section \ref{tarinfo-objects}) for details. -\begin{classdesc}{TarFile}{\optional{name - \optional{, mode\optional{, fileobj}}}} - Open an \emph{(uncompressed)} tar archive \var{name}. +\begin{classdesc}{TarFile}{name=None, mode='r', fileobj=None, + format=DEFAULT_FORMAT, tarinfo=TarInfo, dereference=False, + ignore_zeros=False, encoding=None, pax_headers=None, debug=0, + errorlevel=0} + + All following arguments are optional and can be accessed as instance + attributes as well. + + \var{name} is the pathname of the archive. It can be omitted if + \var{fileobj} is given. In this case, the file object's \member{name} + attribute is used if it exists. + \var{mode} is either \code{'r'} to read from an existing archive, \code{'a'} to append data to an existing file or \code{'w'} to create a new - file overwriting an existing one. \var{mode} defaults to \code{'r'}. + file overwriting an existing one. If \var{fileobj} is given, it is used for reading or writing data. If it can be determined, \var{mode} is overridden by \var{fileobj}'s mode. @@ -165,6 +202,48 @@ \begin{notice} \var{fileobj} is not closed, when \class{TarFile} is closed. \end{notice} + + \var{format} controls the archive format. It must be one of the constants + \constant{USTAR_FORMAT}, \constant{GNU_FORMAT} or \constant{PAX_FORMAT} + that are defined at module level. + \versionadded{2.6} + + The \var{tarinfo} argument can be used to replace the default + \class{TarInfo} class with a different one. + \versionadded{2.6} + + If \var{dereference} is \code{False}, add symbolic and hard links to the + archive. If it is \code{True}, add the content of the target files to the + archive. This has no effect on systems that do not support symbolic links. + + If \var{ignore_zeros} is \code{False}, treat an empty block as the end of + the archive. If it is \var{True}, skip empty (and invalid) blocks and try + to get as many members as possible. This is only useful for reading + concatenated or damaged archives. + + \var{debug} can be set from \code{0} (no debug messages) up to \code{3} + (all debug messages). The messages are written to \code{sys.stderr}. + + If \var{errorlevel} is \code{0}, all errors are ignored when using + \method{extract()}. Nevertheless, they appear as error messages in the + debug output, when debugging is enabled. If \code{1}, all \emph{fatal} + errors are raised as \exception{OSError} or \exception{IOError} exceptions. + If \code{2}, all \emph{non-fatal} errors are raised as \exception{TarError} + exceptions as well. + + The \var{encoding} argument defines the local character encoding. It + defaults to the value from \function{sys.getfilesystemencoding()} or if + that is \code{None} to \code{"ascii"}. \var{encoding} is used only in + connection with the pax format which stores text data in \emph{UTF-8}. If + it is not set correctly, character conversion will fail with a + \exception{UnicodeError}. + \versionadded{2.6} + + The \var{pax_headers} argument must be a dictionary whose elements are + either unicode objects, numbers or strings that can be decoded to unicode + using \var{encoding}. This information will be added to the archive as a + pax global header. + \versionadded{2.6} \end{classdesc} \begin{methoddesc}{open}{...} @@ -279,43 +358,11 @@ \end{methoddesc} \begin{memberdesc}{posix} - If true, create a \POSIX{} 1003.1-1990 compliant archive. GNU - extensions are not used, because they are not part of the \POSIX{} - standard. This limits the length of filenames to at most 256, - link names to 100 characters and the maximum file size to 8 - gigabytes. A \exception{ValueError} is raised if a file exceeds - this limit. If false, create a GNU tar compatible archive. It - will not be \POSIX{} compliant, but can store files without any - of the above restrictions. + Setting this to \constant{True} is equivalent to setting the + \member{format} attribute to \constant{USTAR_FORMAT}, + \constant{False} is equivalent to \constant{GNU_FORMAT}. \versionchanged[\var{posix} defaults to \constant{False}]{2.4} -\end{memberdesc} - -\begin{memberdesc}{dereference} - If false, add symbolic and hard links to archive. If true, add the - content of the target files to the archive. This has no effect on - systems that do not support symbolic links. -\end{memberdesc} - -\begin{memberdesc}{ignore_zeros} - If false, treat an empty block as the end of the archive. If true, - skip empty (and invalid) blocks and try to get as many members as - possible. This is only useful for concatenated or damaged - archives. -\end{memberdesc} - -\begin{memberdesc}{debug=0} - To be set from \code{0} (no debug messages; the default) up to - \code{3} (all debug messages). The messages are written to - \code{sys.stderr}. -\end{memberdesc} - -\begin{memberdesc}{errorlevel} - If \code{0} (the default), all errors are ignored when using - \method{extract()}. Nevertheless, they appear as error messages - in the debug output, when debugging is enabled. If \code{1}, all - \emph{fatal} errors are raised as \exception{OSError} or - \exception{IOError} exceptions. If \code{2}, all \emph{non-fatal} - errors are raised as \exception{TarError} exceptions as well. + \deprecated{2.6}{Use the \member{format} attribute instead.} \end{memberdesc} %----------------- @@ -343,12 +390,16 @@ invalid.]{2.6} \end{methoddesc} -\begin{methoddesc}{tobuf}{posix} - Create a string buffer from a \class{TarInfo} object. - See \class{TarFile}'s \member{posix} attribute for information - on the \var{posix} argument. It defaults to \constant{False}. +\begin{methoddesc}{fromtarfile}{tarfile} + Read the next member from the \class{TarFile} object \var{tarfile} and + return it as a \class{TarInfo} object. + \versionadded{2.6} +\end{methoddesc} - \versionadded[The \var{posix} parameter]{2.5} +\begin{methoddesc}{tobuf}{\optional{format}} + Create a string buffer from a \class{TarInfo} object. See + \class{TarFile}'s \member{format} argument for information. + \versionchanged[The \var{format} parameter]{2.6} \end{methoddesc} A \code{TarInfo} object has the following public data attributes: Modified: python/branches/p3yk/Doc/lib/libtelnetlib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libtelnetlib.tex (original) +++ python/branches/p3yk/Doc/lib/libtelnetlib.tex Fri Apr 27 21:54:29 2007 @@ -23,13 +23,16 @@ SB (Subnegotiation Begin). -\begin{classdesc}{Telnet}{\optional{host\optional{, port}}} +\begin{classdesc}{Telnet}{\optional{host\optional{, port\optional{, timeout}}}} \class{Telnet} represents a connection to a Telnet server. The instance is initially not connected by default; the \method{open()} method must be used to establish a connection. Alternatively, the host name and optional port number can be passed to the constructor, to, in which case the connection to the server will be established before the constructor returns. +The optional \var{timeout} parameter specifies a timeout in seconds for the +connection attempt (if not specified, or passed as None, the global default +timeout setting will be used). Do not reopen an already connected instance. @@ -52,7 +55,7 @@ \class{Telnet} instances have the following methods: -\begin{methoddesc}{read_until}{expected\optional{, timeout}} +\begin{methoddesc}[Telnet]{read_until}{expected\optional{, timeout}} Read until a given string, \var{expected}, is encountered or until \var{timeout} seconds have passed. @@ -61,17 +64,17 @@ is closed and no cooked data is available. \end{methoddesc} -\begin{methoddesc}{read_all}{} +\begin{methoddesc}[Telnet]{read_all}{} Read all data until \EOF; block until connection closed. \end{methoddesc} -\begin{methoddesc}{read_some}{} +\begin{methoddesc}[Telnet]{read_some}{} Read at least one byte of cooked data unless \EOF{} is hit. Return \code{''} if \EOF{} is hit. Block if no data is immediately available. \end{methoddesc} -\begin{methoddesc}{read_very_eager}{} +\begin{methoddesc}[Telnet]{read_very_eager}{} Read everything that can be without blocking in I/O (eager). Raise \exception{EOFError} if connection closed and no cooked data @@ -79,7 +82,7 @@ Do not block unless in the midst of an IAC sequence. \end{methoddesc} -\begin{methoddesc}{read_eager}{} +\begin{methoddesc}[Telnet]{read_eager}{} Read readily available data. Raise \exception{EOFError} if connection closed and no cooked data @@ -87,7 +90,7 @@ Do not block unless in the midst of an IAC sequence. \end{methoddesc} -\begin{methoddesc}{read_lazy}{} +\begin{methoddesc}[Telnet]{read_lazy}{} Process and return data already in the queues (lazy). Raise \exception{EOFError} if connection closed and no data available. @@ -95,7 +98,7 @@ unless in the midst of an IAC sequence. \end{methoddesc} -\begin{methoddesc}{read_very_lazy}{} +\begin{methoddesc}[Telnet]{read_very_lazy}{} Return any data available in the cooked queue (very lazy). Raise \exception{EOFError} if connection closed and no data available. @@ -103,7 +106,7 @@ never blocks. \end{methoddesc} -\begin{methoddesc}{read_sb_data}{} +\begin{methoddesc}[Telnet]{read_sb_data}{} Return the data collected between a SB/SE pair (suboption begin/end). The callback should access these data when it was invoked with a \code{SE} command. This method never blocks. @@ -111,52 +114,55 @@ \versionadded{2.3} \end{methoddesc} -\begin{methoddesc}{open}{host\optional{, port}} +\begin{methoddesc}[Telnet]{open}{host\optional{, port\optional{, timeout}}} Connect to a host. The optional second argument is the port number, which defaults to the standard Telnet port (23). +The optional \var{timeout} parameter specifies a timeout in seconds for the +connection attempt (if not specified, or passed as None, the global default +timeout setting will be used). Do not try to reopen an already connected instance. \end{methoddesc} -\begin{methoddesc}{msg}{msg\optional{, *args}} +\begin{methoddesc}[Telnet]{msg}{msg\optional{, *args}} Print a debug message when the debug level is \code{>} 0. If extra arguments are present, they are substituted in the message using the standard string formatting operator. \end{methoddesc} -\begin{methoddesc}{set_debuglevel}{debuglevel} +\begin{methoddesc}[Telnet]{set_debuglevel}{debuglevel} Set the debug level. The higher the value of \var{debuglevel}, the more debug output you get (on \code{sys.stdout}). \end{methoddesc} -\begin{methoddesc}{close}{} +\begin{methoddesc}[Telnet]{close}{} Close the connection. \end{methoddesc} -\begin{methoddesc}{get_socket}{} +\begin{methoddesc}[Telnet]{get_socket}{} Return the socket object used internally. \end{methoddesc} -\begin{methoddesc}{fileno}{} +\begin{methoddesc}[Telnet]{fileno}{} Return the file descriptor of the socket object used internally. \end{methoddesc} -\begin{methoddesc}{write}{buffer} +\begin{methoddesc}[Telnet]{write}{buffer} Write a string to the socket, doubling any IAC characters. This can block if the connection is blocked. May raise \exception{socket.error} if the connection is closed. \end{methoddesc} -\begin{methoddesc}{interact}{} +\begin{methoddesc}[Telnet]{interact}{} Interaction function, emulates a very dumb Telnet client. \end{methoddesc} -\begin{methoddesc}{mt_interact}{} +\begin{methoddesc}[Telnet]{mt_interact}{} Multithreaded version of \method{interact()}. \end{methoddesc} -\begin{methoddesc}{expect}{list\optional{, timeout}} +\begin{methoddesc}[Telnet]{expect}{list\optional{, timeout}} Read until one from a list of a regular expressions matches. The first argument is a list of regular expressions, either @@ -178,7 +184,7 @@ results are indeterministic, and may depend on the I/O timing. \end{methoddesc} -\begin{methoddesc}{set_option_negotiation_callback}{callback} +\begin{methoddesc}[Telnet]{set_option_negotiation_callback}{callback} Each time a telnet option is read on the input flow, this \var{callback} (if set) is called with the following parameters : callback(telnet socket, command (DO/DONT/WILL/WONT), option). No other Modified: python/branches/p3yk/Doc/lib/libtempfile.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libtempfile.tex (original) +++ python/branches/p3yk/Doc/lib/libtempfile.tex Fri Apr 27 21:54:29 2007 @@ -53,7 +53,7 @@ \begin{funcdesc}{NamedTemporaryFile}{\optional{mode=\code{'w+b'}\optional{, bufsize=\code{-1}\optional{, suffix\optional{, prefix\optional{, - dir}}}}}} + dir\optional{, delete}}}}}}} This function operates exactly as \function{TemporaryFile()} does, except that the file is guaranteed to have a visible name in the file system (on \UNIX, the directory entry is not unlinked). That name can @@ -61,7 +61,27 @@ the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on \UNIX; it cannot on Windows NT or later). +If \var{delete} is true (the default), the file is deleted as soon as +it is closed. \versionadded{2.3} +\versionadded[The \var{delete} parameter]{2.6} +\end{funcdesc} + +\begin{funcdesc}{SpooledTemporaryFile}{\optional{max\_size=\code{0}, + \optional{mode=\code{'w+b'}\optional{, + bufsize=\code{-1}\optional{, + suffix\optional{, prefix\optional{, + dir}}}}}}} +This function operates exactly as \function{TemporaryFile()} does, +except that data is spooled in memory until the file size exceeds +\var{max_size}, or until the file's \function{fileno()} method is +called, at which point the contents are written to disk and operation +proceeds as with \function{TemporaryFile()}. + +The resulting file has one additional method, \function{rollover()}, +which causes the file to roll over to an on-disk file regardless of +its size. +\versionadded{2.6} \end{funcdesc} \begin{funcdesc}{mkstemp}{\optional{suffix\optional{, Modified: python/branches/p3yk/Doc/lib/libtest.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libtest.tex (original) +++ python/branches/p3yk/Doc/lib/libtest.tex Fri Apr 27 21:54:29 2007 @@ -14,11 +14,11 @@ Each module in the \module{test} package whose name starts with \samp{test_} is a testing suite for a specific module or feature. -All new tests should be written using the \refmodule{unittest} module; -using \refmodule{unittest} is not required but makes the tests more -flexible and maintenance of the tests easier. Some older tests are -written to use \refmodule{doctest} and a ``traditional'' testing -style; these styles of tests will not be covered. +All new tests should be written using the \refmodule{unittest} or +\refmodule{doctest} module. Some older tests are +written using a ``traditional'' testing style that compares output +printed to \code{sys.stdout}; this style of test is considered +deprecated. \begin{seealso} \seemodule{unittest}{Writing PyUnit regression tests.} @@ -29,8 +29,8 @@ \subsection{Writing Unit Tests for the \module{test} package% \label{writing-tests}} -It is preferred that tests for the \module{test} package use the -\refmodule{unittest} module and follow a few guidelines. +It is preferred that tests that use the \refmodule{unittest} module +follow a few guidelines. One is to name the test module by starting it with \samp{test_} and end it with the name of the module being tested. The test methods in the test module should start with \samp{test_} and end with @@ -196,7 +196,9 @@ This module defines the following exceptions: \begin{excdesc}{TestFailed} -Exception to be raised when a test fails. +Exception to be raised when a test fails. This is deprecated in favor +of \module{unittest}-based tests and \class{unittest.TestCase}'s +assertion methods. \end{excdesc} \begin{excdesc}{TestSkipped} @@ -273,18 +275,30 @@ Execute \class{unittest.TestCase} subclasses passed to the function. The function scans the classes for methods starting with the prefix \samp{test_} and executes the tests individually. -This is the preferred way to execute tests. -\end{funcdesc} -\begin{funcdesc}{run_suite}{suite\optional{, testclass}} -Execute the \class{unittest.TestSuite} instance \var{suite}. -The optional argument \var{testclass} accepts one of the test classes in the -suite so as to print out more detailed information on where the testing suite -originated from. +It is also legal to pass strings as parameters; these should be keys in +\code{sys.modules}. Each associated module will be scanned by +\code{unittest.TestLoader.loadTestsFromModule()}. This is usually seen in +the following \function{test_main()} function: + +\begin{verbatim} +def test_main(): + test_support.run_unittest(__name__) +\end{verbatim} + +This will run all tests defined in the named module. \end{funcdesc} The \module{test.test_support} module defines the following classes: +\begin{classdesc}{TransientResource}{exc\optional{, **kwargs}} +Create a context manager that raises \class{ResourceDenied} if the specified +exception type is raised. Any keyword arguments are treated as name/value +pairs to be compared against any exception raised with the \code{with} +statement. Only if all pairs match is \class{ResourceDenied} raised. +\versionadded{2.6} +\end{classdesc} + \begin{classdesc}{EnvironmentVarGuard}{} Class used to temporarily set or unset environment variables. Instances can be used as a context manager. Modified: python/branches/p3yk/Doc/lib/libtextwrap.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libtextwrap.tex (original) +++ python/branches/p3yk/Doc/lib/libtextwrap.tex Fri Apr 27 21:54:29 2007 @@ -54,7 +54,7 @@ in indented form. Note that tabs and spaces are both treated as whitespace, but they are -not equal: the lines \code{" {} hello"} and \code{"\textbackslash{}thello"} +not equal: the lines \code{" {} hello"} and \code{"\e thello"} are considered to have no common leading whitespace. (This behaviour is new in Python 2.5; older versions of this module incorrectly expanded tabs before searching for common leading whitespace.) @@ -115,6 +115,13 @@ expansion.} \end{memberdesc} +\begin{memberdesc}{drop_whitespace} +(default: \code{True}) If true, whitespace that, after wrapping, happens +to end up at the beginning or end of a line is dropped (leading whitespace +in the first line is always preserved, though). +\versionadded[Whitespace was always dropped in earlier versions]{2.6} +\end{memberdesc} + \begin{memberdesc}{initial_indent} (default: \code{''}) String that will be prepended to the first line of wrapped output. Counts towards the length of the first line. Modified: python/branches/p3yk/Doc/lib/libthreading.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libthreading.tex (original) +++ python/branches/p3yk/Doc/lib/libthreading.tex Fri Apr 27 21:54:29 2007 @@ -15,17 +15,16 @@ This module defines the following functions and objects: \begin{funcdesc}{activeCount}{} -Return the number of currently active \class{Thread} objects. -The returned count is equal to the length of the list returned by +Return the number of \class{Thread} objects currently alive. The +returned count is equal to the length of the list returned by \function{enumerate()}. -A function that returns the number of currently active threads. \end{funcdesc} -\begin{funcdesc}{Condition}{} +\begin{funcdescni}{Condition}{} A factory function that returns a new condition variable object. A condition variable allows one or more threads to wait until they are notified by another thread. -\end{funcdesc} +\end{funcdescni} \begin{funcdesc}{currentThread}{} Return the current \class{Thread} object, corresponding to the @@ -36,18 +35,18 @@ \end{funcdesc} \begin{funcdesc}{enumerate}{} -Return a list of all currently active \class{Thread} objects. -The list includes daemonic threads, dummy thread objects created -by \function{currentThread()}, and the main thread. It excludes terminated -threads and threads that have not yet been started. +Return a list of all \class{Thread} objects currently alive. The list +includes daemonic threads, dummy thread objects created by +\function{currentThread()}, and the main thread. It excludes +terminated threads and threads that have not yet been started. \end{funcdesc} -\begin{funcdesc}{Event}{} +\begin{funcdescni}{Event}{} A factory function that returns a new event object. An event manages a flag that can be set to true with the \method{set()} method and reset to false with the \method{clear()} method. The \method{wait()} method blocks until the flag is true. -\end{funcdesc} +\end{funcdescni} \begin{classdesc*}{local}{} A class that represents thread-local data. Thread-local data are data @@ -82,14 +81,14 @@ for each time it has acquired it. \end{funcdesc} -\begin{funcdesc}{Semaphore}{\optional{value}} +\begin{funcdescni}{Semaphore}{\optional{value}} A factory function that returns a new semaphore object. A semaphore manages a counter representing the number of \method{release()} calls minus the number of \method{acquire()} calls, plus an initial value. The \method{acquire()} method blocks if necessary until it can return without making the counter negative. If not given, \var{value} defaults to 1. -\end{funcdesc} +\end{funcdescni} \begin{funcdesc}{BoundedSemaphore}{\optional{value}} A factory function that returns a new bounded semaphore object. A bounded @@ -100,12 +99,12 @@ \var{value} defaults to 1. \end{funcdesc} -\begin{classdesc*}{Thread}{} +\begin{classdesc*}{Thread} A class that represents a thread of control. This class can be safely subclassed in a limited fashion. \end{classdesc*} -\begin{classdesc*}{Timer}{} +\begin{classdesc*}{Timer} A thread that executes a function after a specified interval has passed. \end{classdesc*} @@ -183,7 +182,7 @@ All methods are executed atomically. -\begin{methoddesc}{acquire}{\optional{blocking\code{ = 1}}} +\begin{methoddesc}[Lock]{acquire}{\optional{blocking\code{ = 1}}} Acquire a lock, blocking or non-blocking. When invoked without arguments, block until the lock is @@ -198,7 +197,7 @@ without arguments, and return true. \end{methoddesc} -\begin{methoddesc}{release}{} +\begin{methoddesc}[Lock]{release}{} Release a lock. When the lock is locked, reset it to unlocked, and return. If @@ -228,7 +227,7 @@ pair) resets the lock to unlocked and allows another thread blocked in \method{acquire()} to proceed. -\begin{methoddesc}{acquire}{\optional{blocking\code{ = 1}}} +\begin{methoddesc}[RLock]{acquire}{\optional{blocking\code{ = 1}}} Acquire a lock, blocking or non-blocking. When invoked without arguments: if this thread already owns @@ -250,7 +249,7 @@ without arguments, and return true. \end{methoddesc} -\begin{methoddesc}{release}{} +\begin{methoddesc}[RLock]{release}{} Release a lock, decrementing the recursion level. If after the decrement it is zero, reset the lock to unlocked (not owned by any thread), and if any other threads are blocked waiting for the lock to @@ -526,12 +525,9 @@ \method{run()} method in a separate thread of control. Once the thread's activity is started, the thread is considered -'alive' and 'active' (these concepts are almost, but not quite -exactly, the same; their definition is intentionally somewhat -vague). It stops being alive and active when its \method{run()} -method terminates -- either normally, or by raising an unhandled -exception. The \method{isAlive()} method tests whether the thread is -alive. +'alive'. It stops being alive when its \method{run()} method terminates +-- either normally, or by raising an unhandled exception. The +\method{isAlive()} method tests whether the thread is alive. Other threads can call a thread's \method{join()} method. This blocks the calling thread until the thread whose \method{join()} method is @@ -551,14 +547,13 @@ initial thread of control in the Python program. It is not a daemon thread. -There is the possibility that ``dummy thread objects'' are -created. These are thread objects corresponding to ``alien -threads''. These are threads of control started outside the -threading module, such as directly from C code. Dummy thread objects -have limited functionality; they are always considered alive, -active, and daemonic, and cannot be \method{join()}ed. They are never -deleted, since it is impossible to detect the termination of alien -threads. +There is the possibility that ``dummy thread objects'' are created. +These are thread objects corresponding to ``alien threads'', which +are threads of control started outside the threading module, such as +directly from C code. Dummy thread objects have limited +functionality; they are always considered alive and daemonic, and +cannot be \method{join()}ed. They are never deleted, since it is +impossible to detect the termination of alien threads. \begin{classdesc}{Thread}{group=None, target=None, name=None, @@ -646,7 +641,8 @@ Return whether the thread is alive. Roughly, a thread is alive from the moment the \method{start()} method -returns until its \method{run()} method terminates. +returns until its \method{run()} method terminates. The module +function \function{enumerate()} returns a list of all alive threads. \end{methoddesc} \begin{methoddesc}{isDaemon}{} @@ -659,8 +655,8 @@ The initial value is inherited from the creating thread. -The entire Python program exits when no active non-daemon -threads are left. +The entire Python program exits when no alive non-daemon threads are +left. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libtimeit.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libtimeit.tex (original) +++ python/branches/p3yk/Doc/lib/libtimeit.tex Fri Apr 27 21:54:29 2007 @@ -31,6 +31,13 @@ \method{timeit()} method. The \method{repeat()} method is a convenience to call \method{timeit()} multiple times and return a list of results. + +\versionchanged[The \var{stmt} and \var{setup} parameters can now also + take objects that are callable without arguments. This + will embed calls to them in a timer function that will + then be executed by \method{timeit()}. Note that the timing + overhead is a little larger in this case because of the + extra function calls]{2.6} \end{classdesc} \begin{methoddesc}{print_exc}{\optional{file=\constant{None}}} @@ -97,12 +104,30 @@ \end{methoddesc} +Starting with version 2.6, the module also defines two convenience functions: + +\begin{funcdesc}{repeat}{stmt\optional{, setup\optional{, timer\optional{, + repeat\code{=3} \optional{, number\code{=1000000}}}}}} +Create a \class{Timer} instance with the given statement, setup code and timer +function and run its \method{repeat} method with the given repeat count and +\var{number} executions. +\versionadded{2.6} +\end{funcdesc} + +\begin{funcdesc}{timeit}{stmt\optional{, setup\optional{, timer\optional{, + number\code{=1000000}}}}} +Create a \class{Timer} instance with the given statement, setup code and timer +function and run its \method{timeit} method with \var{number} executions. +\versionadded{2.6} +\end{funcdesc} + + \subsection{Command Line Interface} When called as a program from the command line, the following form is used: \begin{verbatim} -python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement ...] +python -m timeit [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement ...] \end{verbatim} where the following options are understood: Modified: python/branches/p3yk/Doc/lib/libturtle.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libturtle.tex (original) +++ python/branches/p3yk/Doc/lib/libturtle.tex Fri Apr 27 21:54:29 2007 @@ -261,7 +261,7 @@ \function{degrees()}, which takes an optional argument letting you specify the number of units corresponding to a full circle: -\begin{methoddesc}{degrees}{\optional{fullcircle}} +\begin{methoddesc}[Turtle]{degrees}{\optional{fullcircle}} \var{fullcircle} is by default 360. This can cause the pen to have any angular units whatever: give \var{fullcircle} 2*$\pi$ for radians, or 400 for gradians. Modified: python/branches/p3yk/Doc/lib/libunittest.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libunittest.tex (original) +++ python/branches/p3yk/Doc/lib/libunittest.tex Fri Apr 27 21:54:29 2007 @@ -91,7 +91,7 @@ \end{seealso} -\subsection{Basic example \label{minimal-example}} +\subsection{Basic example \label{unittest-minimal-example}} The \module{unittest} module provides a rich set of tools for constructing and running tests. This section demonstrates that a @@ -290,6 +290,7 @@ we would end up subclassing \class{SimpleWidgetTestCase} into many small one-method classes such as \class{DefaultWidgetSizeTestCase}. This is time-consuming and + discouraging, so in the same vein as JUnit, \module{unittest} provides a simpler mechanism: @@ -540,7 +541,7 @@ \begin{funcdesc}{main}{\optional{module\optional{, defaultTest\optional{, argv\optional{, - testRunner\optional{, testRunner}}}}}} + testRunner\optional{, testLoader}}}}}} A command-line program that runs a set of tests; this is primarily for making test modules conveniently executable. The simplest use for this function is to include the following line at the end of a @@ -550,6 +551,9 @@ if __name__ == '__main__': unittest.main() \end{verbatim} + + The \var{testRunner} argument can either be a test runner class or + an already created instance of it. \end{funcdesc} In some cases, the existing tests may have been written using the @@ -615,14 +619,14 @@ report failures. \begin{methoddesc}[TestCase]{assert_}{expr\optional{, msg}} -\methodline{failUnless}{expr\optional{, msg}} +\methodline[TestCase]{failUnless}{expr\optional{, msg}} Signal a test failure if \var{expr} is false; the explanation for the error will be \var{msg} if given, otherwise it will be \constant{None}. \end{methoddesc} \begin{methoddesc}[TestCase]{assertEqual}{first, second\optional{, msg}} -\methodline{failUnlessEqual}{first, second\optional{, msg}} +\methodline[TestCase]{failUnlessEqual}{first, second\optional{, msg}} Test that \var{first} and \var{second} are equal. If the values do not compare equal, the test will fail with the explanation given by \var{msg}, or \constant{None}. Note that using \method{failUnlessEqual()} @@ -633,7 +637,7 @@ \end{methoddesc} \begin{methoddesc}[TestCase]{assertNotEqual}{first, second\optional{, msg}} -\methodline{failIfEqual}{first, second\optional{, msg}} +\methodline[TestCase]{failIfEqual}{first, second\optional{, msg}} Test that \var{first} and \var{second} are not equal. If the values do compare equal, the test will fail with the explanation given by \var{msg}, or \constant{None}. Note that using \method{failIfEqual()} @@ -645,7 +649,7 @@ \begin{methoddesc}[TestCase]{assertAlmostEqual}{first, second\optional{, places\optional{, msg}}} -\methodline{failUnlessAlmostEqual}{first, second\optional{, +\methodline[TestCase]{failUnlessAlmostEqual}{first, second\optional{, places\optional{, msg}}} Test that \var{first} and \var{second} are approximately equal by computing the difference, rounding to the given number of \var{places}, @@ -657,7 +661,7 @@ \begin{methoddesc}[TestCase]{assertNotAlmostEqual}{first, second\optional{, places\optional{, msg}}} -\methodline{failIfAlmostEqual}{first, second\optional{, +\methodline[TestCase]{failIfAlmostEqual}{first, second\optional{, places\optional{, msg}}} Test that \var{first} and \var{second} are not approximately equal by computing the difference, rounding to the given number of \var{places}, @@ -668,7 +672,7 @@ \end{methoddesc} \begin{methoddesc}[TestCase]{assertRaises}{exception, callable, \moreargs} -\methodline{failUnlessRaises}{exception, callable, \moreargs} +\methodline[TestCase]{failUnlessRaises}{exception, callable, \moreargs} Test that an exception is raised when \var{callable} is called with any positional or keyword arguments that are also passed to \method{assertRaises()}. The test passes if \var{exception} is Modified: python/branches/p3yk/Doc/lib/liburllib2.tex ============================================================================== --- python/branches/p3yk/Doc/lib/liburllib2.tex (original) +++ python/branches/p3yk/Doc/lib/liburllib2.tex Fri Apr 27 21:54:29 2007 @@ -588,7 +588,7 @@ \class{HTTPCookieProcessor} instances have one attribute: -\begin{memberdesc}{cookiejar} +\begin{memberdesc}[HTTPCookieProcessor]{cookiejar} The \class{cookielib.CookieJar} in which cookies are stored. \end{memberdesc} @@ -817,7 +817,10 @@ import urllib2 # Create an OpenerDirector with support for Basic HTTP Authentication... auth_handler = urllib2.HTTPBasicAuthHandler() -auth_handler.add_password('realm', 'host', 'username', 'password') +auth_handler.add_password(realm='PDQ Application', + uri='https://mahler:8092/site-updates.py', + user='klem', + passwd='kadidd!ehopper') opener = urllib2.build_opener(auth_handler) # ...and install it globally so it can be used with urlopen. urllib2.install_opener(opener) Modified: python/branches/p3yk/Doc/lib/liburlparse.tex ============================================================================== --- python/branches/p3yk/Doc/lib/liburlparse.tex (original) +++ python/branches/p3yk/Doc/lib/liburlparse.tex Fri Apr 27 21:54:29 2007 @@ -157,7 +157,7 @@ for \function{urlparse()}. \note{If \var{url} is an absolute URL (that is, starting with \code{//} - or \code{scheme://}, the \var{url}'s host name and/or scheme + or \code{scheme://}), the \var{url}'s host name and/or scheme will be present in the result. For example:} \begin{verbatim} Modified: python/branches/p3yk/Doc/lib/libwebbrowser.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libwebbrowser.tex (original) +++ python/branches/p3yk/Doc/lib/libwebbrowser.tex Fri Apr 27 21:54:29 2007 @@ -154,20 +154,20 @@ Browser controllers provide two methods which parallel two of the module-level convenience functions: -\begin{funcdesc}{open}{url\optional{, new\optional{, autoraise=1}}} +\begin{methoddesc}[controller]{open}{url\optional{, new\optional{, autoraise=1}}} Display \var{url} using the browser handled by this controller. If \var{new} is 1, a new browser window is opened if possible. If \var{new} is 2, a new browser page ("tab") is opened if possible. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{open_new}{url} +\begin{methoddesc}[controller]{open_new}{url} Open \var{url} in a new window of the browser handled by this controller, if possible, otherwise, open \var{url} in the only browser window. Alias \function{open_new}. -\end{funcdesc} +\end{methoddesc} -\begin{funcdesc}{open_new_tab}{url} +\begin{methoddesc}[controller]{open_new_tab}{url} Open \var{url} in a new page ("tab") of the browser handled by this controller, if possible, otherwise equivalent to \function{open_new}. \versionadded{2.5} -\end{funcdesc} +\end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libwinreg.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libwinreg.tex (original) +++ python/branches/p3yk/Doc/lib/libwinreg.tex Fri Apr 27 21:54:29 2007 @@ -151,7 +151,7 @@ An application should only call \function{FlushKey()} if it requires absolute certainty that registry changes are on disk. - \emph{If you don't know whether a \function{FlushKey()} call is required, it + \note{If you don't know whether a \function{FlushKey()} call is required, it probably isn't.} \end{funcdesc} @@ -393,14 +393,14 @@ \method{Detach()} method to return the integer handle, and also disconnect the Windows handle from the handle object. -\begin{methoddesc}{Close}{} +\begin{methoddesc}[PyHKEY]{Close}{} Closes the underlying Windows handle. If the handle is already closed, no error is raised. \end{methoddesc} -\begin{methoddesc}{Detach}{} +\begin{methoddesc}[PyHKEY]{Detach}{} Detaches the Windows handle from the handle object. The result is an integer (or long on 64 bit Windows) that holds Modified: python/branches/p3yk/Doc/lib/libxmlrpclib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libxmlrpclib.tex (original) +++ python/branches/p3yk/Doc/lib/libxmlrpclib.tex Fri Apr 27 21:54:29 2007 @@ -134,12 +134,12 @@ Servers that support the XML introspection API support some common methods grouped under the reserved \member{system} member: -\begin{methoddesc}{system.listMethods}{} +\begin{methoddesc}[ServerProxy]{system.listMethods}{} This method returns a list of strings, one for each (non-system) method supported by the XML-RPC server. \end{methoddesc} -\begin{methoddesc}{system.methodSignature}{name} +\begin{methoddesc}[ServerProxy]{system.methodSignature}{name} This method takes one parameter, the name of a method implemented by the XML-RPC server.It returns an array of possible signatures for this method. A signature is an array of types. The first of these types is @@ -159,7 +159,7 @@ value will be something other that list. \end{methoddesc} -\begin{methoddesc}{system.methodHelp}{name} +\begin{methoddesc}[ServerProxy]{system.methodHelp}{name} This method takes one parameter, the name of a method implemented by the XML-RPC server. It returns a documentation string describing the use of that method. If no such string is available, an empty string is @@ -184,7 +184,7 @@ It also has the following method, supported mainly for internal use by the unmarshalling code: -\begin{methoddesc}{encode}{out} +\begin{methoddesc}[Boolean]{encode}{out} Write the XML-RPC encoding of this Boolean item to the out stream object. \end{methoddesc} @@ -197,11 +197,11 @@ instance. It has the following methods, supported mainly for internal use by the marshalling/unmarshalling code: -\begin{methoddesc}{decode}{string} +\begin{methoddesc}[DateTime]{decode}{string} Accept a string as the instance's new time value. \end{methoddesc} -\begin{methoddesc}{encode}{out} +\begin{methoddesc}[DateTime]{encode}{out} Write the XML-RPC encoding of this \class{DateTime} item to the \var{out} stream object. \end{methoddesc} @@ -242,11 +242,11 @@ A \class{Fault} object encapsulates the content of an XML-RPC fault tag. Fault objects have the following members: -\begin{memberdesc}{faultCode} +\begin{memberdesc}[Fault]{faultCode} A string indicating the fault type. \end{memberdesc} -\begin{memberdesc}{faultString} +\begin{memberdesc}[Fault]{faultString} A string containing a diagnostic message associated with the fault. \end{memberdesc} @@ -258,19 +258,19 @@ server named by the URI does not exist). It has the following members: -\begin{memberdesc}{url} +\begin{memberdesc}[ProtocolError]{url} The URI or URL that triggered the error. \end{memberdesc} -\begin{memberdesc}{errcode} +\begin{memberdesc}[ProtocolError]{errcode} The error code. \end{memberdesc} -\begin{memberdesc}{errmsg} +\begin{memberdesc}[ProtocolError]{errmsg} The error message or diagnostic string. \end{memberdesc} -\begin{memberdesc}{headers} +\begin{memberdesc}[ProtocolError]{headers} A string containing the headers of the HTTP/HTTPS request that triggered the error. \end{memberdesc} Modified: python/branches/p3yk/Doc/lib/libzipfile.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libzipfile.tex (original) +++ python/branches/p3yk/Doc/lib/libzipfile.tex Fri Apr 27 21:54:29 2007 @@ -141,6 +141,34 @@ Return a list of archive members by name. \end{methoddesc} +\begin{methoddesc}{open}{name\optional{, mode\optional{, pwd}}} + Extract a member from the archive as a file-like object (ZipExtFile). + \var{name} is the name of the file in the archive. The \var{mode} + parameter, if included, must be one of the following: \code{'r'} (the + default), \code{'U'}, or \code{'rU'}. Choosing \code{'U'} or + \code{'rU'} will enable universal newline support in the read-only + object. \var{pwd} is the password used for encrypted files. + \begin{notice} + The file-like object is read-only and provides the following methods: + \method{read()}, \method{readline()}, \method{readlines()}, + \method{__iter__()}, \method{next()}. + \end{notice} + \begin{notice} + If the ZipFile was created by passing in a file-like object as the + first argument to the constructor, then the object returned by + \method{open()} shares the ZipFile's file pointer. Under these + circumstances, the object returned by \method{open()} should not + be used after any additional operations are performed on the + ZipFile object. If the ZipFile was created by passing in a string + (the filename) as the first argument to the constructor, then + \method{open()} will create a new file object that will be held + by the ZipExtFile, allowing it to operate independently of the + ZipFile. + \end{notice} + + \versionadded{2.6} +\end{methoddesc} + \begin{methoddesc}{printdir}{} Print a table of contents for the archive to \code{sys.stdout}. \end{methoddesc} Modified: python/branches/p3yk/Doc/lib/libzlib.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libzlib.tex (original) +++ python/branches/p3yk/Doc/lib/libzlib.tex Fri Apr 27 21:54:29 2007 @@ -131,7 +131,7 @@ Decompression objects support the following methods, and two attributes: -\begin{memberdesc}{unused_data} +\begin{memberdesc}[Decompress]{unused_data} A string which contains any bytes past the end of the compressed data. That is, this remains \code{""} until the last byte that contains compression data is available. If the whole string turned out to @@ -145,7 +145,7 @@ \member{unused_data} attribute is no longer the empty string. \end{memberdesc} -\begin{memberdesc}{unconsumed_tail} +\begin{memberdesc}[Decompress]{unconsumed_tail} A string that contains any data that was not consumed by the last \method{decompress} call because it exceeded the limit for the uncompressed data buffer. This data has not yet been seen by the zlib Modified: python/branches/p3yk/Doc/mac/libframework.tex ============================================================================== --- python/branches/p3yk/Doc/mac/libframework.tex (original) +++ python/branches/p3yk/Doc/mac/libframework.tex Fri Apr 27 21:54:29 2007 @@ -189,8 +189,6 @@ Window objects have the following methods, among others: -\setindexsubitem{(Window method)} - \begin{methoddesc}[Window]{open}{} Override this method to open a window. Store the MacOS window-id in \member{self.wid} and call the \method{do_postopen()} method to @@ -218,7 +216,7 @@ An update event for the window was received. Redraw the window. \end{methoddesc} -\begin{methoddesc}{do_activate}{activate, event} +\begin{methoddesc}[Window]{do_activate}{activate, event} The window was activated (\code{\var{activate} == 1}) or deactivated (\code{\var{activate} == 0}). Handle things like focus highlighting, etc. Modified: python/branches/p3yk/Doc/mac/libmacic.tex ============================================================================== --- python/branches/p3yk/Doc/mac/libmacic.tex (original) +++ python/branches/p3yk/Doc/mac/libmacic.tex Fri Apr 27 21:54:29 2007 @@ -68,14 +68,14 @@ following methods: -\begin{methoddesc}{launchurl}{url\optional{, hint}} +\begin{methoddesc}[IC]{launchurl}{url\optional{, hint}} Parse the given URL, launch the correct application and pass it the URL. The optional \var{hint} can be a scheme name such as \code{'mailto:'}, in which case incomplete URLs are completed with this scheme. If \var{hint} is not provided, incomplete URLs are invalid. \end{methoddesc} -\begin{methoddesc}{parseurl}{data\optional{, start\optional{, end\optional{, hint}}}} +\begin{methoddesc}[IC]{parseurl}{data\optional{, start\optional{, end\optional{, hint}}}} Find an URL somewhere in \var{data} and return start position, end position and the URL. The optional \var{start} and \var{end} can be used to limit the search, so for instance if a user clicks in a long @@ -85,7 +85,7 @@ complete incomplete URLs. \end{methoddesc} -\begin{methoddesc}{mapfile}{file} +\begin{methoddesc}[IC]{mapfile}{file} Return the mapping entry for the given \var{file}, which can be passed as either a filename or an \function{FSSpec()} result, and which need not exist. @@ -106,7 +106,7 @@ file and \var{entryname} is the name of this entry. \end{methoddesc} -\begin{methoddesc}{maptypecreator}{type, creator\optional{, filename}} +\begin{methoddesc}[IC]{maptypecreator}{type, creator\optional{, filename}} Return the mapping entry for files with given 4-character \var{type} and \var{creator} codes. The optional \var{filename} may be specified to further help finding the correct entry (if the creator code is @@ -115,7 +115,7 @@ The mapping entry is returned in the same format as for \var{mapfile}. \end{methoddesc} -\begin{methoddesc}{settypecreator}{file} +\begin{methoddesc}[IC]{settypecreator}{file} Given an existing \var{file}, specified either as a filename or as an \function{FSSpec()} result, set its creator and type correctly based on its extension. The finder is told about the change, so the finder Modified: python/branches/p3yk/Doc/mac/undoc.tex ============================================================================== --- python/branches/p3yk/Doc/mac/undoc.tex (original) +++ python/branches/p3yk/Doc/mac/undoc.tex Fri Apr 27 21:54:29 2007 @@ -21,7 +21,7 @@ \modulesynopsis{Helper module for BuildApplet, BuildApplication and macfreeze.} -\deprecated{2.4} +\deprecated{2.4}{} \section{\module{cfmfile} --- Code Fragment Resource module} \declaremodule{standard}{cfmfile} @@ -33,7 +33,7 @@ used by BuildApplication to combine all plugin modules to a single executable. -\deprecated{2.4} +\deprecated{2.4}{} \section{\module{icopen} --- Internet Config replacement for \method{open()}} \declaremodule{standard}{icopen} Modified: python/branches/p3yk/Doc/mac/using.tex ============================================================================== --- python/branches/p3yk/Doc/mac/using.tex (original) +++ python/branches/p3yk/Doc/mac/using.tex Fri Apr 27 21:54:29 2007 @@ -2,7 +2,7 @@ \sectionauthor{Bob Savage}{bobsavage at mac.com} Python on a Macintosh running Mac OS X is in principle very similar to -Python on any other \UNIX platform, but there are a number of additional +Python on any other \UNIX{} platform, but there are a number of additional features such as the IDE and the Package Manager that are worth pointing out. Python on Mac OS 9 or earlier can be quite different from Python on @@ -13,206 +13,166 @@ \section{Getting and Installing MacPython \label{getting-OSX}} -Mac OS X 10.3 comes with Python 2.3 pre-installed by Apple. -This installation does not come with the IDE and other additions, however, -so to get these you need to install the \program{MacPython for Panther additions} -from the MacPython website, \url{http://www.cwi.nl/\textasciitilde jack/macpython}. - -For MacPython 2.4, or for any MacPython on earlier releases of Mac OS X, -you need to install a full distribution from the same website. +Mac OS X 10.4 comes with Python 2.3 pre-installed by Apple. However, you are +encouraged to install the most recent version of Python from the Python website +(\url{http://www.python.org}). A ``universal binary'' build of Python 2.5, which +runs natively on the Mac's new Intel and legacy PPC CPU's, is available there. What you get after installing is a number of things: \begin{itemize} - \item A \file{MacPython-2.3} folder in your \file{Applications} - folder. In here you find the PythonIDE Integrated Development Environment; - PythonLauncher, which handles double-clicking Python scripts from - the Finder; and the Package Manager. - - \item A fairly standard \UNIX{} commandline Python interpreter in - \file{/usr/local/bin/python}, but without the usual - \file{/usr/local/lib/python}. - - \item A framework \file{/Library/Frameworks/Python.framework}, where - all the action really is, but which you usually do not have to be aware of. +\item A \file{MacPython 2.5} folder in your \file{Applications} folder. In here + you find IDLE, the development environment that is a standard part of official + Python distributions; PythonLauncher, which handles double-clicking Python + scripts from the Finder; and the ``Build Applet'' tool, which allows you to + package Python scripts as standalone applications on your system. + +\item A framework \file{/Library/Frameworks/Python.framework}, which includes + the Python executable and libraries. The installer adds this location to your + shell path. To uninstall MacPython, you can simply remove these three + things. A symlink to the Python executable is placed in /usr/local/bin/. \end{itemize} -To uninstall MacPython you can simply remove these three things. +The Apple-provided build of Python is installed in +\file{/System/Library/Frameworks/Python.framework} and \file{/usr/bin/python}, +respectively. You should never modify or delete these, as they are +Apple-controlled and are used by Apple- or third-party software. + +IDLE includes a help menu that allows you to access Python documentation. If you +are completely new to Python you should start reading the tutorial introduction +in that document. -If you use the ``additions'' installer to install on top of an existing -Apple-Python you will not get the framework and the commandline interpreter, -as they have been installed by Apple already, in -\file{/System/Library/Frameworks/Python.framework} and -\file{/usr/bin/python}, respectively. You should in principle never modify -or delete these, as they are Apple-controlled and may be used by Apple- or -third-party software. - -PythonIDE contains an Apple Help Viewer book called "MacPython Help" -which you can access through its help menu. If you are completely new to -Python you should start reading the IDE introduction in that document. +If you are familiar with Python on other \UNIX{} platforms you should read the +section on running Python scripts from the \UNIX{} shell. -If you are familiar with Python on other \UNIX{} platforms you should -read the section on running Python scripts from the \UNIX{} shell. \subsection{How to run a Python script} -Your best way to get started with Python on Mac OS X is through the PythonIDE -integrated development environment, see section \ref{IDE} and use the Help -menu when the IDE is running. - -If you want to run Python scripts from the Terminal window command line -or from the Finder you first need an editor to create your script. -Mac OS X comes with a number of standard \UNIX{} command line editors, -\program{vim} and \program{emacs} among them. If you want a more Mac-like -editor \program{BBEdit} or \program{TextWrangler} from Bare Bones Software -(see \url{http://www.barebones.com/products/bbedit/index.shtml}) are -good choices. \program{AppleWorks} or any other -word processor that can save files in ASCII is also a possibility, including -\program{TextEdit} which is included with OS X. +Your best way to get started with Python on Mac OS X is through the IDLE +integrated development environment, see section \ref{IDE} and use the Help menu +when the IDE is running. + +If you want to run Python scripts from the Terminal window command line or from +the Finder you first need an editor to create your script. Mac OS X comes with a +number of standard \UNIX{} command line editors, \program{vim} and +\program{emacs} among them. If you want a more Mac-like editor, \program{BBEdit} +or \program{TextWrangler} from Bare Bones Software (see +\url{http://www.barebones.com/products/bbedit/index.shtml}) are good choices, as +is \program{TextMate} (see \url{http://macromates.com/}). Other editors include +\program{Gvim} (\url{http://macvim.org}) and \program{Aquamacs} +(\url{http://aquamacs.org}). To run your script from the Terminal window you must make sure that -\file{/usr/local/bin} is in your shell search path. +\file{/usr/local/bin} is in your shell search path. To run your script from the Finder you have two options: + \begin{itemize} - \item Drag it to \program{PythonLauncher} - \item Select \program{PythonLauncher} as the default application - to open your script (or any .py script) through the finder Info window - and double-click it. +\item Drag it to \program{PythonLauncher} +\item Select \program{PythonLauncher} as the default application to open your + script (or any .py script) through the finder Info window and double-click it. + \program{PythonLauncher} has various preferences to control how your script is + launched. Option-dragging allows you to change these for one invocation, or + use its Preferences menu to change things globally. \end{itemize} -PythonLauncher has various preferences to control how your script is launched. -Option-dragging allows you to change these for one invocation, or use its -Preferences menu to change things globally. \subsection{Running scripts with a GUI \label{osx-gui-scripts}} -There is one Mac OS X quirk that you need to be aware of: programs -that talk to the Aqua window manager (in other words, anything that has a GUI) -need to be run in a special way. Use \program{pythonw} instead of \program{python} -to start such scripts. - -\subsection{configuration} - -MacPython honours all standard \UNIX{} environment variables such as -\envvar{PYTHONPATH}, but setting these variables for programs started -from the Finder is non-standard -as the Finder does not read your \file{.profile} or \file{.cshrc} at startup. -You need to create a file \file{\textasciitilde /.MacOSX/environment.plist}. -See Apple's Technical Document QA1067 for details. +With older versions of Python, there is one Mac OS X quirk that you need to be +aware of: programs that talk to the Aqua window manager (in other words, +anything that has a GUI) need to be run in a special way. Use \program{pythonw} +instead of \program{python} to start such scripts. + +With Python 2.5, you can use either \program{python} or \program{pythonw}. + +\subsection{Configuration} + +Python on OS X honors all standard \UNIX{} environment variables such as +\envvar{PYTHONPATH}, but setting these variables for programs started from the +Finder is non-standard as the Finder does not read your \file{.profile} or +\file{.cshrc} at startup. You need to create a file \file{\textasciitilde + /.MacOSX/environment.plist}. See Apple's Technical Document QA1067 for +details. -Installing additional Python packages is most easily done through the -Package Manager, see the MacPython Help Book for details. +For more information on installation Python packages in MacPython, see section +\ref{mac-package-manager}, ``Installing Additional Python Packages.'' \section{The IDE\label{IDE}} -The \program{Python IDE} (Integrated Development Environment) is a -separate application that acts as a text editor for your Python code, -a class browser, a graphical debugger, and more. - -The online Python Help contains a quick walkthrough of the IDE that -shows the major features and how to use them. - -\subsection{Using the ``Python Interactive'' window} - -Use this window like you would use a normal \UNIX{} command line -interpreter. - -\subsection{Writing a Python Script \label{IDEwrite}} - -In addition to using the \program{Python IDE} interactively, you can -also type out a complete Python program, saving it incrementally, and -execute it or smaller selections of it. - -You can create a new script, open a previously saved script, and save -your currently open script by selecting the appropriate item in the -``File'' menu. Dropping a Python script onto the -\program{Python IDE} will open it for editing. - -When the \program{Python IDE} saves a script, it uses the creator code -settings which are available by clicking on the small black triangle -on the top right of the document window, and selecting ``save -options''. The default is to save the file with the \program{Python -IDE} as the creator, this means that you can open the file for editing -by simply double-clicking on its icon. You might want to change this -behaviour so that it will be opened by the -\program{PythonLauncher}, and run. To do this simply choose -``PythonLauncher'' from the ``save options''. Note that these -options are associated with the \emph{file} not the application. - - -\subsection{Executing a script from within the IDE - \label{IDEexecution}} - -You can run the script in the frontmost window of the \program{Python -IDE} by hitting the run all button. You should be aware, however that -if you use the Python convention \samp{if __name__ == "__main__":} the -script will \emph{not} be ``__main__'' by default. To get that -behaviour you must select the ``Run as __main__'' option from the -small black triangle on the top right of the document window. Note -that this option is associated with the \emph{file} not the -application. It \emph{will} stay active after a save, however; to shut -this feature off simply select it again. - - -\subsection{``Save as'' versus ``Save as Applet'' - \label{IDEapplet}} - -When you are done writing your Python script you have the option of -saving it as an ``applet'' (by selecting ``Save as applet'' from the -``File'' menu). This has a significant advantage in that you can drop -files or folders onto it, to pass them to the applet the way -command-line users would type them onto the command-line to pass them -as arguments to the script. However, you should make sure to save the -applet as a separate file, do not overwrite the script you are -writing, because you will not be able to edit it again. - -Accessing the items passed to the applet via ``drag-and-drop'' is done -using the standard \member{sys.argv} mechanism. See the general -documentation for more -% need to link to the appropriate place in non-Mac docs - -Note that saving a script as an applet will not make it runnable on a -system without a Python installation. - -%\subsection{Debugger} -% **NEED INFO HERE** - -%\subsection{Module Browser} -% **NEED INFO HERE** - -%\subsection{Profiler} -% **NEED INFO HERE** -% end IDE - -%\subsection{The ``Scripts'' menu} -% **NEED INFO HERE** - -\section{The Package Manager} - -Historically MacPython came with a number of useful extension packages -included, because most Macintosh users do not have access to a development -environment and C compiler. For Mac OS X that bundling is no longer done, -but a new mechanism has been made available to allow easy access to -extension packages. - -The Python Package Manager helps you installing additional packages -that enhance Python. It determines the exact MacOS version and Python -version you have and uses that information to download a database that -has packages that are tested and tried on that combination. In other -words: if something is in your Package Manager window but does not work -you are free to blame the database maintainer. - -PackageManager then checks which of the packages you have installed and -which ones are not. This should also work when you have installed packages -outside of PackageManager. You can select packages and install them, -and PackageManager will work out the requirements and install these too. - -Often PackageManager will list a package in two flavors: binary and -source. Binary should always work, source will only work if you have -installed the Apple Developer Tools. PackageManager will warn you about -this, and also about other external dependencies. +MacPython ships with the standard IDLE development environment. A good +introduction to using IDLE can be found at +\url{http://hkn.eecs.berkeley.edu/~dyoo/python/idle_intro/index.html}. + + +\section{Installing Additional Python Packages \label{mac-package-manager}} + +There are several methods to install additional Python packages: + +\begin{itemize} +\item \url{http://pythonmac.org/packages/} contains selected compiled packages + for Python 2.5, 2.4, and 2.3. +\item Packages can be installed via the standard Python distutils mode + (\samp{python setup.py install}). +\item Many packages can also be installed via the \program{setuptools} + extension. +\end{itemize} + + +\section{GUI Programming on the Mac} + +There are several options for building GUI applications on the Mac with Python. + +\emph{PyObjC} is a Python binding to Apple's Objective-C/Cocoa framework, which +is the foundation of most modern Mac development. Information on PyObjC is +available from \url{http://pybojc.sourceforge.net}. + +The standard Python GUI toolkit is \module{Tkinter}, based on the cross-platform +Tk toolkit (\url{http://www.tcl.tk}). An Aqua-native version of Tk is bundled +with OS X by Apple, and the latest version can be downloaded and installed from +\url{http://www.activestate.com}; it can also be built from source. + +\emph{wxPython} is another popular cross-platform GUI toolkit that runs natively +on Mac OS X. Packages and documentation are available from +\url{http://www.wxpython.org}. + +\emph{PyQt} is another popular cross-platform GUI toolkit that runs natively on +Mac OS X. More information can be found at +\url{http://www.riverbankcomputing.co.uk/pyqt/}. + + +\section{Distributing Python Applications on the Mac} + +The ``Build Applet'' tool that is placed in the MacPython 2.5 folder is fine for +packaging small Python scripts on your own machine to run as a standard Mac +application. This tool, however, is not robust enough to distribute Python +applications to other users. + +The standard tool for deploying standalone Python applications on the Mac is +\program{py2app}. More information on installing and using py2app can be found +at \url{http://undefined.org/python/\#py2app}. + +\section{Application Scripting} + +Python can also be used to script other Mac applications via Apple's Open +Scripting Architecture (OSA); see +\url{http://appscript.sourceforge.net}. Appscript is a high-level, user-friendly +Apple event bridge that allows you to control scriptable Mac OS X applications +using ordinary Python scripts. Appscript makes Python a serious alternative to +Apple's own \emph{AppleScript} language for automating your Mac. A related +package, \emph{PyOSA}, is an OSA language component for the Python scripting +language, allowing Python code to be executed by any OSA-enabled application +(Script Editor, Mail, iTunes, etc.). PyOSA makes Python a full peer to +AppleScript. + +\section{Other Resources} + +The MacPython mailing list is an excellent support resource for Python users and +developers on the Mac: + +\url{http://www.python.org/community/sigs/current/pythonmac-sig/} + +Another useful resource is the MacPython wiki: -PackageManager is available as a separate application and also as a -function of the IDE, through the File->Package Manager menu entry. +\url{http://wiki.python.org/moin/MacPython} Modified: python/branches/p3yk/Doc/ref/ref1.tex ============================================================================== --- python/branches/p3yk/Doc/ref/ref1.tex (original) +++ python/branches/p3yk/Doc/ref/ref1.tex Fri Apr 27 21:54:29 2007 @@ -93,7 +93,7 @@ \index{syntax} \index{notation} -\begin{productionlist} +\begin{productionlist}[*] \production{name}{\token{lc_letter} (\token{lc_letter} | "_")*} \production{lc_letter}{"a"..."z"} \end{productionlist} Modified: python/branches/p3yk/Doc/ref/ref3.tex ============================================================================== --- python/branches/p3yk/Doc/ref/ref3.tex (original) +++ python/branches/p3yk/Doc/ref/ref3.tex Fri Apr 27 21:54:29 2007 @@ -218,7 +218,7 @@ \indexii{integer}{representation} \item[Floating point numbers] -These represent machine-level double precision floating point numbers. +These represent machine-level double precision floating point numbers. You are at the mercy of the underlying machine architecture (and C or Java implementation) for the accepted range and handling of overflow. Python does not support single-precision floating point numbers; the @@ -470,7 +470,7 @@ \obindex{function} \obindex{user-defined function} -Special attributes: +Special attributes: \begin{tableiii}{lll}{member}{Attribute}{Meaning}{} \lineiii{__doc__}{The function's documentation string, or @@ -860,12 +860,12 @@ \begin{description} \item[Code objects] -Code objects represent \emph{byte-compiled} executable Python code, or +Code objects represent \emph{byte-compiled} executable Python code, or \emph{bytecode}. The difference between a code object and a function object is that the function object contains an explicit reference to the function's globals (the module in which it -was defined), while a code object contains no context; +was defined), while a code object contains no context; also the default argument values are stored in the function object, not in the code object (because they represent values calculated at run-time). Unlike function objects, code objects are immutable and @@ -1069,7 +1069,7 @@ %========================================================================= \section{New-style and classic classes} -Classes and instances come in two flavors: old-style or classic, and new-style. +Classes and instances come in two flavors: old-style or classic, and new-style. Up to Python 2.1, old-style classes were the only flavour available to the user. The concept of (old-style) class is unrelated to the concept of type: if @@ -1244,7 +1244,7 @@ string object. If a class defines \method{__repr__()} but not \method{__str__()}, then \method{__repr__()} is also used when an ``informal'' string -representation of instances of that class is required. +representation of instances of that class is required. This is typically used for debugging, so it is important that the representation is information-rich and unambiguous. @@ -1280,10 +1280,14 @@ \code{\var{x}!=\var{y}} calls \code{\var{x}.__ne__(\var{y})}, \code{\var{x}>\var{y}} calls \code{\var{x}.__gt__(\var{y})}, and \code{\var{x}>=\var{y}} calls \code{\var{x}.__ge__(\var{y})}. -These methods can return any value, but if the comparison operator is -used in a Boolean context, the return value should be interpretable as -a Boolean value, else a \exception{TypeError} will be raised. -By convention, \code{False} is used for false and \code{True} for true. + +A rich comparison method may return the singleton \code{NotImplemented} if it +does not implement the operation for a given pair of arguments. +By convention, \code{False} and \code{True} are returned for a successful +comparison. However, these methods can return any value, so if the +comparison operator is used in a Boolean context (e.g., in the condition +of an \code{if} statement), Python will call \function{bool()} on the +value to determine if the result is true or false. There are no implied relationships among the comparison operators. The truth of \code{\var{x}==\var{y}} does not imply that \code{\var{x}!=\var{y}} @@ -1297,9 +1301,7 @@ \method{__ge__()} are each other's reflection, and \method{__eq__()} and \method{__ne__()} are their own reflection. -Arguments to rich comparison methods are never coerced. A rich -comparison method may return \code{NotImplemented} if it does not -implement the operation for a given pair of arguments. +Arguments to rich comparison methods are never coerced. \end{methoddesc} \begin{methoddesc}[object]{__cmp__}{self, other} @@ -1399,7 +1401,7 @@ dictionary). \var{name} is the attribute name, \var{value} is the value to be assigned to it. -If \method{__setattr__()} wants to assign to an instance attribute, it +If \method{__setattr__()} wants to assign to an instance attribute, it should not simply execute \samp{self.\var{name} = value} --- this would cause a recursive call to itself. Instead, it should insert the value in the dictionary of instance attributes, e.g., @@ -1422,8 +1424,8 @@ \begin{methoddesc}[object]{__getattribute__}{self, name} Called unconditionally to implement attribute accesses for instances -of the class. If the class also defines \method{__getattr__()}, the latter -will not be called unless \method{__getattribute__()} either calls it +of the class. If the class also defines \method{__getattr__()}, the latter +will not be called unless \method{__getattribute__()} either calls it explicitly or raises an \exception{AttributeError}. This method should return the (computed) attribute value or raise an \exception{AttributeError} exception. @@ -1475,7 +1477,7 @@ The default behavior for attribute access is to get, set, or delete the attribute from an object's dictionary. For instance, \code{a.x} has a lookup chain starting with \code{a.__dict__['x']}, then -\code{type(a).__dict__['x']}, and continuing +\code{type(a).__dict__['x']}, and continuing through the base classes of \code{type(a)} excluding metaclasses. However, if the looked-up value is an object defining one of the descriptor @@ -1489,14 +1491,14 @@ How the arguments are assembled depends on \code{a}: \begin{itemize} - + \item[Direct Call] The simplest and least common call is when user code directly invokes a descriptor method: \code{x.__get__(a)}. \item[Instance Binding] If binding to a new-style object instance, \code{a.x} is transformed into the call: \code{type(a).__dict__['x'].__get__(a, type(a))}. - + \item[Class Binding] If binding to a new-style class, \code{A.x} is transformed into the call: \code{A.__dict__['x'].__get__(None, A)}. @@ -1505,7 +1507,7 @@ \code{obj.__class__.__mro__} for the base class \code{A} immediately preceding \code{B} and then invokes the descriptor with the call: \code{A.__dict__['m'].__get__(obj, A)}. - + \end{itemize} For instance bindings, the precedence of descriptor invocation depends @@ -1518,7 +1520,7 @@ Python methods (including \function{staticmethod()} and \function{classmethod()}) are implemented as non-data descriptors. Accordingly, instances can redefine and override methods. This allows individual instances to acquire -behaviors that differ from other instances of the same class. +behaviors that differ from other instances of the same class. The \function{property()} function is implemented as a data descriptor. Accordingly, instances cannot override the behavior of a property. @@ -1536,14 +1538,14 @@ variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because \var{__dict__} is not created for each instance. - + \begin{datadesc}{__slots__} This class variable can be assigned a string, iterable, or sequence of strings with variable names used by instances. If defined in a new-style class, \var{__slots__} reserves space for the declared variables and prevents the automatic creation of \var{__dict__} and \var{__weakref__} for each instance. -\versionadded{2.2} +\versionadded{2.2} \end{datadesc} \noindent @@ -1555,23 +1557,23 @@ variables not listed in the \var{__slots__} definition. Attempts to assign to an unlisted variable name raises \exception{AttributeError}. If dynamic assignment of new variables is desired, then add \code{'__dict__'} to the -sequence of strings in the \var{__slots__} declaration. +sequence of strings in the \var{__slots__} declaration. \versionchanged[Previously, adding \code{'__dict__'} to the \var{__slots__} declaration would not enable the assignment of new attributes not -specifically listed in the sequence of instance variable names]{2.3} +specifically listed in the sequence of instance variable names]{2.3} \item Without a \var{__weakref__} variable for each instance, classes defining \var{__slots__} do not support weak references to its instances. If weak reference support is needed, then add \code{'__weakref__'} to the -sequence of strings in the \var{__slots__} declaration. +sequence of strings in the \var{__slots__} declaration. \versionchanged[Previously, adding \code{'__weakref__'} to the \var{__slots__} -declaration would not enable support for weak references]{2.3} +declaration would not enable support for weak references]{2.3} \item \var{__slots__} are implemented at the class level by creating descriptors (\ref{descriptors}) for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by \var{__slots__}; otherwise, the class attribute would -overwrite the descriptor assignment. +overwrite the descriptor assignment. \item If a class defines a slot also defined in a base class, the instance variable defined by the base class slot is inaccessible (except by retrieving @@ -1580,14 +1582,19 @@ \item The action of a \var{__slots__} declaration is limited to the class where it is defined. As a result, subclasses will have a \var{__dict__} -unless they also define \var{__slots__}. +unless they also define \var{__slots__}. \item \var{__slots__} do not work for classes derived from ``variable-length'' -built-in types such as \class{long}, \class{str} and \class{tuple}. +built-in types such as \class{long}, \class{str} and \class{tuple}. \item Any non-string iterable may be assigned to \var{__slots__}. Mappings may also be used; however, in the future, special meaning may -be assigned to the values corresponding to each key. +be assigned to the values corresponding to each key. + +\item \var{__class__} assignment works only if both classes have the +same \var{__slots__}. +\versionchanged[Previously, \var{__class__} assignment raised an error +if either new or old class had \var{__slots__}]{2.6} \end{itemize} @@ -1613,7 +1620,7 @@ This variable can be any callable accepting arguments for \code{name}, \code{bases}, and \code{dict}. Upon class creation, the callable is used instead of the built-in \function{type()}. -\versionadded{2.2} +\versionadded{2.2} \end{datadesc} The appropriate metaclass is determined by the following precedence rules: @@ -1630,7 +1637,7 @@ \item Otherwise, the old-style, classic metaclass (types.ClassType) is used. -\end{itemize} +\end{itemize} The potential uses for metaclasses are boundless. Some ideas that have been explored including logging, interface checking, automatic delegation, @@ -1663,15 +1670,15 @@ that mappings provide the methods \method{keys()}, \method{values()}, \method{items()}, \method{has_key()}, \method{get()}, \method{clear()}, \method{setdefault()}, \method{iterkeys()}, \method{itervalues()}, -\method{iteritems()}, \method{pop()}, \method{popitem()}, +\method{iteritems()}, \method{pop()}, \method{popitem()}, \method{copy()}, and \method{update()} behaving similar to those for Python's standard dictionary objects. The \module{UserDict} module provides a \class{DictMixin} class to help create those methods from a base set of \method{__getitem__()}, \method{__setitem__()}, -\method{__delitem__()}, and \method{keys()}. +\method{__delitem__()}, and \method{keys()}. Mutable sequences should provide methods \method{append()}, \method{count()}, \method{index()}, -\method{extend()}, +\method{extend()}, \method{insert()}, \method{pop()}, \method{remove()}, \method{reverse()} and \method{sort()}, like Python standard list objects. Finally, sequence types should implement addition (meaning concatenation) and @@ -1694,12 +1701,12 @@ \ttindex{items()} \ttindex{iterkeys()} \ttindex{itervalues()} - \ttindex{iteritems()} + \ttindex{iteritems()} \ttindex{has_key()} \ttindex{get()} \ttindex{setdefault()} - \ttindex{pop()} - \ttindex{popitem()} + \ttindex{pop()} + \ttindex{popitem()} \ttindex{clear()} \ttindex{copy()} \ttindex{update()} @@ -1707,7 +1714,7 @@ \withsubitem{(sequence object method)}{ \ttindex{append()} \ttindex{count()} - \ttindex{extend()} + \ttindex{extend()} \ttindex{index()} \ttindex{insert()} \ttindex{pop()} @@ -1721,7 +1728,7 @@ \ttindex{__rmul__()} \ttindex{__imul__()} \ttindex{__contains__()} - \ttindex{__iter__()}} + \ttindex{__iter__()}} \withsubitem{(numeric object method)} \begin{methoddesc}[container object]{__len__}{self} @@ -1744,7 +1751,7 @@ (after any special interpretation of negative values), \exception{IndexError} should be raised. For mapping types, if \var{key} is missing (not in the container), -\exception{KeyError} should be raised. +\exception{KeyError} should be raised. \note{\keyword{for} loops expect that an \exception{IndexError} will be raised for illegal indexes to allow proper detection of the end of the sequence.} @@ -1943,7 +1950,7 @@ \methodline[numeric object]{__rmul__}{self, other} \methodline[numeric object]{__rdiv__}{self, other} \methodline[numeric object]{__rtruediv__}{self, other} -\methodline[numeric object]{__rfloordiv__}{self, other} +\methodline[numeric object]{__rfloordiv__}{self, other} \methodline[numeric object]{__rmod__}{self, other} \methodline[numeric object]{__rdivmod__}{self, other} \methodline[numeric object]{__rpow__}{self, other} @@ -1964,7 +1971,7 @@ For operands of the same type, it is assumed that if the non-reflected method (such as \method{__add__()}) fails the operation is not supported, which is why the reflected method - is not called.} + is not called.} For instance, to evaluate the expression \var{x}\code{-}\var{y}, where \var{y} is an instance of a class that has an \method{__rsub__()} method, \code{\var{y}.__rsub__(\var{x})} @@ -1989,7 +1996,7 @@ \methodline[numeric object]{__idiv__}{self, other} \methodline[numeric object]{__itruediv__}{self, other} \methodline[numeric object]{__ifloordiv__}{self, other} -\methodline[numeric object]{__imod__}{self, other} +\methodline[numeric object]{__imod__}{self, other} \methodline[numeric object]{__ipow__}{self, other\optional{, modulo}} \methodline[numeric object]{__ilshift__}{self, other} \methodline[numeric object]{__irshift__}{self, other} Modified: python/branches/p3yk/Doc/ref/ref5.tex ============================================================================== --- python/branches/p3yk/Doc/ref/ref5.tex (original) +++ python/branches/p3yk/Doc/ref/ref5.tex Fri Apr 27 21:54:29 2007 @@ -56,7 +56,7 @@ \production{enclosure} {\token{parenth_form} | \token{list_display}} \productioncont{| \token{generator_expression} | \token{dict_display}} - \productioncont{| \token{string_conversion}} + \productioncont{| \token{string_conversion} | \token{yield_atom}} \end{productionlist} @@ -65,6 +65,7 @@ \index{identifier} An identifier occurring as an atom is a name. See +section \ref{identifiers} for lexical definition and section~\ref{naming} for documentation of naming and binding. When the name is bound to an object, evaluation of the atom yields @@ -154,22 +155,20 @@ square brackets: \begin{productionlist} - \production{test} - {\token{or_test} | \token{lambda_form}} - \production{testlist} - {\token{test} ( "," \token{test} )* [ "," ]} \production{list_display} - {"[" [\token{listmaker}] "]"} - \production{listmaker} - {\token{expression} ( \token{list_for} - | ( "," \token{expression} )* [","] )} - \production{list_iter} - {\token{list_for} | \token{list_if}} + {"[" [\token{expression_list} | \token{list_comprehension}] "]"} + \production{list_comprehension} + {\token{expression} \token{list_for}} \production{list_for} - {"for" \token{expression_list} "in" \token{testlist} + {"for" \token{target_list} "in" \token{old_expression_list} [\token{list_iter}]} + \production{old_expression_list} + {\token{old_expression} + [("," \token{old_expression})+ [","]]} + \production{list_iter} + {\token{list_for} | \token{list_if}} \production{list_if} - {"if" \token{test} [\token{list_iter}]} + {"if" \token{old_expression} [\token{list_iter}]} \end{productionlist} A list display yields a new list object. Its contents are specified @@ -200,19 +199,18 @@ \begin{productionlist} \production{generator_expression} - {"(" \token{test} \token{genexpr_for} ")"} + {"(" \token{expression} \token{genexpr_for} ")"} \production{genexpr_for} - {"for" \token{expression_list} "in" \token{test} + {"for" \token{target_list} "in" \token{or_test} [\token{genexpr_iter}]} \production{genexpr_iter} {\token{genexpr_for} | \token{genexpr_if}} \production{genexpr_if} - {"if" \token{test} [\token{genexpr_iter}]} + {"if" \token{old_expression} [\token{genexpr_iter}]} \end{productionlist} A generator expression yields a new generator object. \obindex{generator} -\obindex{generator expression} It consists of a single expression followed by at least one \keyword{for} clause and zero or more \keyword{for} or \keyword{if} clauses. The iterating values of the new generator are those that @@ -268,6 +266,142 @@ \indexii{immutable}{object} +\subsection{Yield expressions\label{yieldexpr}} +\kwindex{yield} +\indexii{yield}{expression} +\indexii{generator}{function} + +\begin{productionlist} + \production{yield_atom} + {"(" \token{yield_expression} ")"} + \production{yield_expression} + {"yield" [\token{expression_list}]} +\end{productionlist} + +\versionadded{2.5} + +The \keyword{yield} expression is only used when defining a generator +function, and can only be used in the body of a function definition. +Using a \keyword{yield} expression in a function definition is +sufficient to cause that definition to create a generator function +instead of a normal function. + +When a generator function is called, it returns an iterator known as a +generator. That generator then controls the execution of a generator +function. The execution starts when one of the generator's methods is +called. At that time, the execution proceeds to the first +\keyword{yield} expression, where it is suspended again, returning the +value of \grammartoken{expression_list} to generator's caller. By +suspended we mean that all local state is retained, including the +current bindings of local variables, the instruction pointer, and the +internal evaluation stack. When the execution is resumed by calling +one of the generator's methods, the function can proceed exactly as +if the \keyword{yield} expression was just another external call. +The value of the \keyword{yield} expression after resuming depends on +the method which resumed the execution. + +\index{coroutine} + +All of this makes generator functions quite similar to coroutines; they +yield multiple times, they have more than one entry point and their +execution can be suspended. The only difference is that a generator +function cannot control where should the execution continue after it +yields; the control is always transfered to the generator's caller. + +\obindex{generator} + +The following generator's methods can be used to control the execution +of a generator function: + +\exindex{StopIteration} + +\begin{methoddesc}[generator]{next}{} + Starts the execution of a generator function or resumes it at the + last executed \keyword{yield} expression. When a generator function + is resumed with a \method{next()} method, the current \keyword{yield} + expression always evaluates to \constant{None}. The execution then + continues to the next \keyword{yield} expression, where the generator + is suspended again, and the value of the + \grammartoken{expression_list} is returned to \method{next()}'s + caller. If the generator exits without yielding another value, a + \exception{StopIteration} exception is raised. +\end{methoddesc} + +\begin{methoddesc}[generator]{send}{value} + Resumes the execution and ``sends'' a value into the generator + function. The \code{value} argument becomes the result of the + current \keyword{yield} expression. The \method{send()} method + returns the next value yielded by the generator, or raises + \exception{StopIteration} if the generator exits without yielding + another value. + When \method{send()} is called to start the generator, it must be + called with \constant{None} as the argument, because there is no + \keyword{yield} expression that could receieve the value. +\end{methoddesc} + +\begin{methoddesc}[generator]{throw} + {type\optional{, value\optional{, traceback}}} + Raises an exception of type \code{type} at the point where generator + was paused, and returns the next value yielded by the generator + function. If the generator exits without yielding another value, a + \exception{StopIteration} exception is raised. If the generator + function does not catch the passed-in exception, or raises a + different exception, then that exception propagates to the caller. +\end{methoddesc} + +\exindex{GeneratorExit} + +\begin{methoddesc}[generator]{close}{} + Raises a \exception{GeneratorExit} at the point where the generator + function was paused. If the generator function then raises + \exception{StopIteration} (by exiting normally, or due to already + being closed) or \exception{GeneratorExit} (by not catching the + exception), close returns to its caller. If the generator yields a + value, a \exception{RuntimeError} is raised. If the generator raises + any other exception, it is propagated to the caller. \method{close} + does nothing if the generator has already exited due to an exception + or normal exit. +\end{methoddesc} + +Here is a simple example that demonstrates the behavior of generators +and generator functions: + +\begin{verbatim} +>>> def echo(value=None): +... print "Execution starts when 'next()' is called for the first time." +... try: +... while True: +... try: +... value = (yield value) +... except GeneratorExit: +... # never catch GeneratorExit +... raise +... except Exception, e: +... value = e +... finally: +... print "Don't forget to clean up when 'close()' is called." +... +>>> generator = echo(1) +>>> print generator.next() +Execution starts when 'next()' is called for the first time. +1 +>>> print generator.next() +None +>>> print generator.send(2) +2 +>>> generator.throw(TypeError, "spam") +TypeError('spam',) +>>> generator.close() +Don't forget to clean up when 'close()' is called. +\end{verbatim} + +\begin{seealso} + \seepep{0342}{Coroutines via Enhanced Generators} + {The proposal to enhance the API and syntax of generators, + making them usable as simple coroutines.} +\end{seealso} + + \section{Primaries\label{primaries}} \index{primary} @@ -430,9 +564,8 @@ \begin{productionlist} \production{call} - {\token{primary} "(" [\token{argument_list} [","]] ")"} - {\token{primary} "(" [\token{argument_list} [","] | - \token{test} \token{genexpr_for} ] ")"} + {\token{primary} "(" [\token{argument_list} [","]} + \productioncont{ | \token{expression} \token{genexpr_for}] ")"} \production{argument_list} {\token{positional_arguments} ["," \token{keyword_arguments}]} \productioncont{ ["," "*" \token{expression}]} @@ -765,10 +898,9 @@ operations: \begin{productionlist} - % The empty groups below prevent conversion to guillemets. \production{shift_expr} {\token{a_expr} - | \token{shift_expr} ( "<{}<" | ">{}>" ) \token{a_expr}} + | \token{shift_expr} ( "<<" | ">>" ) \token{a_expr}} \end{productionlist} These operators accept plain or long integers as arguments. The @@ -966,14 +1098,18 @@ \section{Boolean operations\label{Booleans}} +\indexii{Conditional}{expression} \indexii{Boolean}{operation} Boolean operations have the lowest priority of all Python operations: \begin{productionlist} \production{expression} - {\token{or_test} [\token{if} \token{or_test} \token{else} - \token{test}] | \token{lambda_form}} + {\token{conditional_expression} | \token{lambda_form}} + \production{old_expression} + {\token{or_test} | \token{old_lambda_form}} + \production{conditional_expression} + {\token{or_test} ["if" \token{or_test} "else" \token{expression}]} \production{or_test} {\token{and_test} | \token{or_test} "or" \token{and_test}} \production{and_test} @@ -1025,6 +1161,8 @@ \begin{productionlist} \production{lambda_form} {"lambda" [\token{parameter_list}]: \token{expression}} + \production{old_lambda_form} + {"lambda" [\token{parameter_list}]: \token{old_expression}} \end{productionlist} Lambda forms (lambda expressions) have the same syntactic position as Modified: python/branches/p3yk/Doc/ref/ref6.tex ============================================================================== --- python/branches/p3yk/Doc/ref/ref6.tex (original) +++ python/branches/p3yk/Doc/ref/ref6.tex Fri Apr 27 21:54:29 2007 @@ -106,7 +106,8 @@ \begin{productionlist} \production{assignment_stmt} - {(\token{target_list} "=")+ \token{expression_list}} + {(\token{target_list} "=")+ + (\token{expression_list} | \token{yield_expression})} \production{target_list} {\token{target} ("," \token{target})* [","]} \production{target} @@ -271,11 +272,11 @@ \begin{productionlist} \production{augmented_assignment_stmt} - {\token{target} \token{augop} \token{expression_list}} + {\token{target} \token{augop} + (\token{expression_list} | \token{yield_expression})} \production{augop} {"+=" | "-=" | "*=" | "/=" | "\%=" | "**="} - % The empty groups below prevent conversion to guillemets. - \productioncont{| ">{}>=" | "<{}<=" | "\&=" | "\textasciicircum=" | "|="} + \productioncont{| ">>=" | "<<=" | "\&=" | "\textasciicircum=" | "|="} \end{productionlist} (See section~\ref{primaries} for the syntax definitions for the last @@ -404,7 +405,7 @@ \begin{productionlist} \production{yield_stmt} - {"yield" \token{expression_list}} + {\token{yield_expression}} \end{productionlist} \index{generator!function} @@ -573,15 +574,19 @@ \production{import_stmt} {"import" \token{module} ["as" \token{name}] ( "," \token{module} ["as" \token{name}] )*} - \productioncont{| "from" \token{module} "import" \token{identifier} + \productioncont{| "from" \token{relative_module} "import" \token{identifier} ["as" \token{name}]} \productioncont{ ( "," \token{identifier} ["as" \token{name}] )*} - \productioncont{| "from" \token{module} "import" "(" \token{identifier} - ["as" \token{name}]} + \productioncont{| "from" \token{relative_module} "import" "(" + \token{identifier} ["as" \token{name}]} \productioncont{ ( "," \token{identifier} ["as" \token{name}] )* [","] ")"} \productioncont{| "from" \token{module} "import" "*"} \production{module} {(\token{identifier} ".")* \token{identifier}} + \production{relative_module} + {"."* \token{module} | "."+} + \production{name} + {\token{identifier}} \end{productionlist} Import statements are executed in two steps: (1) find a module, and @@ -700,8 +705,10 @@ \begin{productionlist}[*] \production{future_statement} - {"from" "__future__" "import" feature ["as" name] ("," feature ["as" name])*} - \productioncont{| "from" "__future__" "import" "(" feature ["as" name] ("," feature ["as" name])* [","] ")"} + {"from" "__future__" "import" feature ["as" name]} + \productioncont{ ("," feature ["as" name])*} + \productioncont{| "from" "__future__" "import" "(" feature ["as" name]} + \productioncont{ ("," feature ["as" name])* [","] ")"} \production{feature}{identifier} \production{name}{identifier} \end{productionlist} @@ -718,9 +725,10 @@ \end{itemize} -The features recognized by Python 2.3 are \samp{generators}, -\samp{division} and \samp{nested_scopes}. \samp{generators} and -\samp{nested_scopes} are redundant in 2.3 because they are always +The features recognized by Python 2.5 are \samp{absolute_import}, +\samp{division}, \samp{generators}, \samp{nested_scopes} and +\samp{with_statement}. \samp{generators} and \samp{nested_scopes} +are redundant in Python version 2.3 and above because they are always enabled. A future statement is recognized and treated specially at compile Modified: python/branches/p3yk/Doc/ref/ref7.tex ============================================================================== --- python/branches/p3yk/Doc/ref/ref7.tex (original) +++ python/branches/p3yk/Doc/ref/ref7.tex Fri Apr 27 21:54:29 2007 @@ -313,7 +313,7 @@ \begin{productionlist} \production{with_stmt} - {"with" \token{expression} ["as" target] ":" \token{suite}} + {"with" \token{expression} ["as" \token{target}] ":" \token{suite}} \end{productionlist} The execution of the \keyword{with} statement proceeds as follows: Modified: python/branches/p3yk/Doc/texinputs/python.sty ============================================================================== --- python/branches/p3yk/Doc/texinputs/python.sty (original) +++ python/branches/p3yk/Doc/texinputs/python.sty Fri Apr 27 21:54:29 2007 @@ -612,7 +612,7 @@ \newenvironment{cfuncdesc}[4][\py at badkey]{ \begin{fulllineitems} \cfuncline{#2}{#3}{#4} - \ifx#1\@undefined\else% + \ifx\@undefined#1\relax\else% \emph{Return value: \textbf{#1}.}\\ \fi }{\end{fulllineitems}} @@ -629,7 +629,7 @@ \newenvironment{ctypedesc}[2][\py at badkey]{ \begin{fulllineitems} \item[\bfcode{#2}% - \ifx#1\@undefined% + \ifx\@undefined#1\relax% \index{#2@{\py at idxcode{#2}} (C type)} \else% \index{#2@{\py at idxcode{#1}} (C type)} @@ -712,7 +712,7 @@ % \begin{methoddesc}[classname]{methodname}{args} \newcommand{\methodline}[3][\@undefined]{ \methodlineni{#2}{#3} - \ifx#1\@undefined + \ifx\@undefined#1\relax \index{#2@{\py at idxcode{#2()}} (\py at thisclass\ method)} \else \index{#2@{\py at idxcode{#2()}} (#1 method)} @@ -720,7 +720,7 @@ } \newenvironment{methoddesc}[3][\@undefined]{ \begin{fulllineitems} - \ifx#1\@undefined + \ifx\@undefined#1\relax \methodline{#2}{#3} \else \def\py at thisclass{#1} @@ -740,7 +740,7 @@ % object data attribute -------------------------------------------------- % \begin{memberdesc}[classname]{membername} \newcommand{\memberline}[2][\py at classbadkey]{% - \ifx#1\@undefined + \ifx\@undefined#1\relax \memberlineni{#2} \index{#2@{\py at idxcode{#2}} (\py at thisclass\ attribute)} \else @@ -750,7 +750,7 @@ } \newenvironment{memberdesc}[2][\py at classbadkey]{ \begin{fulllineitems} - \ifx#1\@undefined + \ifx\@undefined#1\relax \memberline{#2} \else \def\py at thisclass{#1} @@ -1046,14 +1046,14 @@ % \versionchanged[short explanation]{2.0} % \newcommand{\versionadded}[2][\py at badkey]{% - \ifx#1\@undefined% + \ifx\@undefined#1\relax% { New in version #2. }% \else% { New in version #2:\ #1. }% \fi% } \newcommand{\versionchanged}[2][\py at badkey]{% - \ifx#1\@undefined% + \ifx\@undefined#1\relax% { Changed in version #2. }% \else% { Changed in version #2:\ #1. }% Modified: python/branches/p3yk/Doc/tut/tut.tex ============================================================================== --- python/branches/p3yk/Doc/tut/tut.tex (original) +++ python/branches/p3yk/Doc/tut/tut.tex Fri Apr 27 21:54:29 2007 @@ -813,7 +813,7 @@ IndexError: string index out of range \end{verbatim} -The best way to remember how slices work is to think of the indices as +One way to remember how slices work is to think of the indices as pointing \emph{between} characters, with the left edge of the first character numbered 0. Then the right edge of the last character of a string of \var{n} characters has index \var{n}, for example: @@ -4312,8 +4312,7 @@ \end{verbatim} -The only rule necessary to explain the semantics is the resolution -rule used for class attribute references. This is depth-first, +For old-style classes, the only rule is depth-first, left-to-right. Thus, if an attribute is not found in \class{DerivedClassName}, it is searched in \class{Base1}, then (recursively) in the base classes of \class{Base1}, and only if it is @@ -4328,16 +4327,26 @@ rule makes no differences between direct and inherited attributes of \class{Base1}.) -It is clear that indiscriminate use of multiple inheritance is a -maintenance nightmare, given the reliance in Python on conventions to -avoid accidental name conflicts. A well-known problem with multiple -inheritance is a class derived from two classes that happen to have a -common base class. While it is easy enough to figure out what happens -in this case (the instance will have a single copy of ``instance -variables'' or data attributes used by the common base class), it is -not clear that these semantics are in any way useful. +For new-style classes, the method resolution order changes dynamically +to support cooperative calls to \function{super()}. This approach +is known in some other multiple-inheritance languages as call-next-method +and is more powerful than the super call found in single-inheritance languages. + +With new-style classes, dynamic ordering is necessary because all +cases of multiple inheritance exhibit one or more diamond relationships +(where one at least one of the parent classes can be accessed through +multiple paths from the bottommost class). For example, all new-style +classes inherit from \class{object}, so any case of multiple inheritance +provides more than one path to reach \class{object}. To keep the +base classes from being accessed more than once, the dynamic algorithm +linearizes the search order in a way that preserves the left-to-right +ordering specified in each class, that calls each parent only once, and +that is monotonic (meaning that a class can be subclassed without affecting +the precedence order of its parents). Taken together, these properties +make it possible to design reliable and extensible classes with +multiple inheritance. For more detail, see +\url{http://www.python.org/download/releases/2.3/mro/}. -%% XXX Add rules for new-style MRO? \section{Private Variables \label{private}} Modified: python/branches/p3yk/Doc/whatsnew/whatsnew23.tex ============================================================================== --- python/branches/p3yk/Doc/whatsnew/whatsnew23.tex (original) +++ python/branches/p3yk/Doc/whatsnew/whatsnew23.tex Fri Apr 27 21:54:29 2007 @@ -896,7 +896,7 @@ \end{seealso} %====================================================================== -\section{PEP 307: Pickle Enhancements \label{section-pep305}} +\section{PEP 307: Pickle Enhancements \label{section-pep307}} The \module{pickle} and \module{cPickle} modules received some attention during the 2.3 development cycle. In 2.2, new-style classes Modified: python/branches/p3yk/Doc/whatsnew/whatsnew24.tex ============================================================================== --- python/branches/p3yk/Doc/whatsnew/whatsnew24.tex (original) +++ python/branches/p3yk/Doc/whatsnew/whatsnew24.tex Fri Apr 27 21:54:29 2007 @@ -1291,7 +1291,7 @@ [1, 2, 3] >>> list(i2) # Run the second iterator to exhaustion [1, 2, 3] ->\end{verbatim} +\end{verbatim} Note that \function{tee()} has to keep copies of the values returned by the iterator; in the worst case, it may need to keep all of them. Modified: python/branches/p3yk/Doc/whatsnew/whatsnew25.tex ============================================================================== --- python/branches/p3yk/Doc/whatsnew/whatsnew25.tex (original) +++ python/branches/p3yk/Doc/whatsnew/whatsnew25.tex Fri Apr 27 21:54:29 2007 @@ -1294,6 +1294,17 @@ (Contributed by Alan McIntyre and committed at the NeedForSpeed sprint.) % Patch 1442927 +\item It's now illegal to mix iterating over a file +with \code{for line in \var{file}} and calling +the file object's \method{read()}/\method{readline()}/\method{readlines()} +methods. Iteration uses an internal buffer and the +\method{read*()} methods don't use that buffer. +Instead they would return the data following the buffer, causing the +data to appear out of order. Mixing iteration and these methods will +now trigger a \exception{ValueError} from the \method{read*()} method. +(Implemented by Thomas Wouters.) +% Patch 1397960 + \item The \module{struct} module now compiles structure format strings into an internal representation and caches this representation, yielding a 20\% speedup. (Contributed by Bob Ippolito @@ -1704,8 +1715,8 @@ In Python code, netlink addresses are represented as a tuple of 2 integers, \code{(\var{pid}, \var{group_mask})}. -Two new methods on socket objects, \method{recv_buf(\var{buffer})} and -\method{recvfrom_buf(\var{buffer})}, store the received data in an object +Two new methods on socket objects, \method{recv_into(\var{buffer})} and +\method{recvfrom_into(\var{buffer})}, store the received data in an object that supports the buffer protocol instead of returning the data as a string. This means you can put the data directly into an array or a memory-mapped file. Modified: python/branches/p3yk/Doc/whatsnew/whatsnew26.tex ============================================================================== --- python/branches/p3yk/Doc/whatsnew/whatsnew26.tex (original) +++ python/branches/p3yk/Doc/whatsnew/whatsnew26.tex Fri Apr 27 21:54:29 2007 @@ -2,6 +2,46 @@ \usepackage{distutils} % $Id$ +% Rules for maintenance: +% +% * Anyone can add text to this document. Do not spend very much time +% on the wording of your changes, because your text will probably +% get rewritten to some degree. +% +% * The maintainer will go through Misc/NEWS periodically and add +% changes; it's therefore more important to add your changes to +% Misc/NEWS than to this file. +% +% * This is not a complete list of every single change; completeness +% is the purpose of Misc/NEWS. Some changes I consider too small +% or esoteric to include. If such a change is added to the text, +% I'll just remove it. (This is another reason you shouldn't spend +% too much time on writing your addition.) +% +% * If you want to draw your new text to the attention of the +% maintainer, add 'XXX' to the beginning of the paragraph or +% section. +% +% * It's OK to just add a fragmentary note about a change. For +% example: "XXX Describe the transmogrify() function added to the +% socket module." The maintainer will research the change and +% write the necessary text. +% +% * You can comment out your additions if you like, but it's not +% necessary (especially when a final release is some months away). +% +% * Credit the author of a patch or bugfix. Just the name is +% sufficient; the e-mail address isn't necessary. +% +% * It's helpful to add the bug/patch number as a comment: +% +% % Patch 12345 +% XXX Describe the transmogrify() function added to the socket +% module. +% (Contributed by P.Y. Developer.) +% +% This saves the maintainer the effort of going through the SVN log +% when researching a change. \title{What's New in Python 2.6} \release{0.0} @@ -29,6 +69,9 @@ % Large, PEP-level features and changes should be described here. +% Should there be a new section here for 3k migration? +% Or perhaps a more general section describing module changes/deprecation? +% sets module deprecated %====================================================================== \section{Other Language Changes} @@ -37,7 +80,13 @@ language. \begin{itemize} -\item TBD + +% Bug 1569356 +\item An obscure change: when you use the the \function{locals()} +function inside a \keyword{class} statement, the resulting dictionary +no longer returns free variables. (Free variables, in this case, are +variables referred to in the \keyword{class} statement +that aren't attributes of the class.) \end{itemize} @@ -47,7 +96,10 @@ \begin{itemize} -\item Optimizations should be described here. +% Patch 1624059 +\item Internally, a bit is now set in type objects to indicate some of +the standard built-in types. This speeds up checking if an object is +a subclass of one of these types. (Contributed by Neal Norwitz.) \end{itemize} @@ -67,6 +119,71 @@ \begin{itemize} +\item New data type in the \module{collections} module: +\class{NamedTuple(\var{typename}, \var{fieldnames})} is a factory function that +creates subclasses of the standard tuple whose fields are accessible +by name as well as index. For example: + +\begin{verbatim} +var_type = collections.NamedTuple('variable', + 'id name type size') +var = var_type(1, 'frequency', 'int', 4) + +print var[0], var.id # Equivalent +print var[2], var.type # Equivalent +\end{verbatim} + +(Contributed by Raymond Hettinger.) + +\item New method in the \module{curses} module: +for a window, \method{chgat()} changes the display characters for a +certain number of characters on a single line. + +\begin{verbatim} +# Boldface text starting at y=0,x=21 +# and affecting the rest of the line. +stdscr.chgat(0,21, curses.A_BOLD) +\end{verbatim} + +(Contributed by Fabian Kreutz.) + +\item New function in the \module{heapq} module: +\function{merge(iter1, iter2, ...)} +takes any number of iterables that return data +\emph{in sorted order}, +and +returns a new iterator that returns the contents of +all the iterators, also in sorted order. For example: + +\begin{verbatim} +heapq.merge([1, 3, 5, 9], [2, 8, 16]) -> + [1, 2, 3, 5, 8, 9, 16] +\end{verbatim} + +(Contributed by Raymond Hettinger.) + +\item New function in the \module{itertools} module: +\function{izip_longest(iter1, iter2, ...\optional{, fillvalue})} +makes tuples from each of the elements; if some of the iterables +are shorter than others, the missing values +are set to \var{fillvalue}. For example: + +\begin{verbatim} +itertools.izip_longest([1,2,3], [1,2,3,4,5]) -> + [(1, 1), (2, 2), (3, 3), (None, 4), (None, 5)] +\end{verbatim} + +(Contributed by Raymond Hettinger.) + +% Patch #1490190 +\item New functions in the \module{posix} module: \function{chflags()} +and \function{lchflags()} are wrappers for the corresponding system +calls (where they're available). Constants for the flag values are +defined in the \module{stat} module; some possible values include +\constant{UF_IMMUTABLE} to signal the file may not be changed and +\constant{UF_APPEND} to indicate that data can only be appended to the +file. (Contributed by M. Levinson.) + \item The \module{smtplib} module now supports SMTP over SSL thanks to the addition of the \class{SMTP_SSL} class. This class supports an interface identical to the existing \class{SMTP} Modified: python/branches/p3yk/Include/fileobject.h ============================================================================== --- python/branches/p3yk/Include/fileobject.h (original) +++ python/branches/p3yk/Include/fileobject.h Fri Apr 27 21:54:29 2007 @@ -55,6 +55,11 @@ char *Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *); size_t Py_UniversalNewlineFread(char *, size_t, FILE *, PyObject *); +/* A routine to do sanity checking on the file mode string. returns + non-zero on if an exception occurred +*/ +int _PyFile_SanitizeMode(char *mode); + #ifdef __cplusplus } #endif Modified: python/branches/p3yk/Include/pydebug.h ============================================================================== --- python/branches/p3yk/Include/pydebug.h (original) +++ python/branches/p3yk/Include/pydebug.h Fri Apr 27 21:54:29 2007 @@ -8,6 +8,7 @@ PyAPI_DATA(int) Py_DebugFlag; PyAPI_DATA(int) Py_VerboseFlag; PyAPI_DATA(int) Py_InteractiveFlag; +PyAPI_DATA(int) Py_InspectFlag; PyAPI_DATA(int) Py_OptimizeFlag; PyAPI_DATA(int) Py_NoSiteFlag; PyAPI_DATA(int) Py_UseClassExceptionsFlag; Modified: python/branches/p3yk/Include/pystate.h ============================================================================== --- python/branches/p3yk/Include/pystate.h (original) +++ python/branches/p3yk/Include/pystate.h Fri Apr 27 21:54:29 2007 @@ -21,6 +21,7 @@ PyObject *modules; PyObject *sysdict; PyObject *builtins; + PyObject *modules_reloading; PyObject *codec_search_path; PyObject *codec_search_cache; Modified: python/branches/p3yk/Include/setobject.h ============================================================================== --- python/branches/p3yk/Include/setobject.h (original) +++ python/branches/p3yk/Include/setobject.h Fri Apr 27 21:54:29 2007 @@ -82,7 +82,8 @@ PyAPI_FUNC(int) PySet_Contains(PyObject *anyset, PyObject *key); PyAPI_FUNC(int) PySet_Discard(PyObject *set, PyObject *key); PyAPI_FUNC(int) PySet_Add(PyObject *set, PyObject *key); -PyAPI_FUNC(int) _PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **entry); +PyAPI_FUNC(int) _PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **key); +PyAPI_FUNC(int) _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash); PyAPI_FUNC(PyObject *) PySet_Pop(PyObject *set); PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable); Modified: python/branches/p3yk/LICENSE ============================================================================== --- python/branches/p3yk/LICENSE (original) +++ python/branches/p3yk/LICENSE Fri Apr 27 21:54:29 2007 @@ -52,7 +52,9 @@ 2.4.1 2.4 2005 PSF yes 2.4.2 2.4.1 2005 PSF yes 2.4.3 2.4.2 2006 PSF yes + 2.4.4 2.4.3 2006 PSF yes 2.5 2.4 2006 PSF yes + 2.5.1 2.5 2007 PSF yes Footnotes: Modified: python/branches/p3yk/Lib/Bastion.py ============================================================================== --- python/branches/p3yk/Lib/Bastion.py (original) +++ python/branches/p3yk/Lib/Bastion.py Fri Apr 27 21:54:29 2007 @@ -97,7 +97,7 @@ """ - raise RuntimeError, "This code is not secure in Python 2.2 and 2.3" + raise RuntimeError, "This code is not secure in Python 2.2 and later" # Note: we define *two* ad-hoc functions here, get1 and get2. # Both are intended to be called in the same way: get(name). Modified: python/branches/p3yk/Lib/CGIHTTPServer.py ============================================================================== --- python/branches/p3yk/Lib/CGIHTTPServer.py (original) +++ python/branches/p3yk/Lib/CGIHTTPServer.py Fri Apr 27 21:54:29 2007 @@ -197,6 +197,9 @@ length = self.headers.getheader('content-length') if length: env['CONTENT_LENGTH'] = length + referer = self.headers.getheader('referer') + if referer: + env['HTTP_REFERER'] = referer accept = [] for line in self.headers.getallmatchingheaders('accept'): if line[:1] in "\t\n\r ": @@ -214,7 +217,7 @@ # Since we're setting the env in the parent, provide empty # values to override previously set values for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH', - 'HTTP_USER_AGENT', 'HTTP_COOKIE'): + 'HTTP_USER_AGENT', 'HTTP_COOKIE', 'HTTP_REFERER'): env.setdefault(k, "") os.environ.update(env) Modified: python/branches/p3yk/Lib/ConfigParser.py ============================================================================== --- python/branches/p3yk/Lib/ConfigParser.py (original) +++ python/branches/p3yk/Lib/ConfigParser.py Fri Apr 27 21:54:29 2007 @@ -594,7 +594,8 @@ self._interpolate_some(option, L, rawval, section, vars, 1) return ''.join(L) - _interpvar_match = re.compile(r"%\(([^)]+)\)s").match + _interpvar_re = re.compile(r"%\(([^)]+)\)s") + _badpercent_re = re.compile(r"%[^%]|%$") def _interpolate_some(self, option, accum, rest, section, map, depth): if depth > MAX_INTERPOLATION_DEPTH: @@ -613,7 +614,7 @@ accum.append("%") rest = rest[2:] elif c == "(": - m = self._interpvar_match(rest) + m = self._interpvar_re.match(rest) if m is None: raise InterpolationSyntaxError(option, section, "bad interpolation variable reference %r" % rest) @@ -638,4 +639,12 @@ """Set an option. Extend ConfigParser.set: check for string values.""" if not isinstance(value, basestring): raise TypeError("option values must be strings") + # check for bad percent signs: + # first, replace all "good" interpolations + tmp_value = self._interpvar_re.sub('', value) + # then, check if there's a lone percent sign left + m = self._badpercent_re.search(tmp_value) + if m: + raise ValueError("invalid interpolation syntax in %r at " + "position %d" % (value, m.start())) ConfigParser.set(self, section, option, value) Modified: python/branches/p3yk/Lib/DocXMLRPCServer.py ============================================================================== --- python/branches/p3yk/Lib/DocXMLRPCServer.py (original) +++ python/branches/p3yk/Lib/DocXMLRPCServer.py Fri Apr 27 21:54:29 2007 @@ -252,8 +252,10 @@ """ def __init__(self, addr, requestHandler=DocXMLRPCRequestHandler, - logRequests=1): - SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests) + logRequests=1, allow_none=False, encoding=None, + bind_and_activate=True): + SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests, + allow_none, encoding, bind_and_activate) XMLRPCDocGenerator.__init__(self) class DocCGIXMLRPCRequestHandler( CGIXMLRPCRequestHandler, Modified: python/branches/p3yk/Lib/HTMLParser.py ============================================================================== --- python/branches/p3yk/Lib/HTMLParser.py (original) +++ python/branches/p3yk/Lib/HTMLParser.py Fri Apr 27 21:54:29 2007 @@ -358,12 +358,30 @@ self.error("unknown declaration: %r" % (data,)) # Internal -- helper to remove special character quoting + entitydefs = None def unescape(self, s): if '&' not in s: return s - s = s.replace("<", "<") - s = s.replace(">", ">") - s = s.replace("'", "'") - s = s.replace(""", '"') - s = s.replace("&", "&") # Must be last - return s + def replaceEntities(s): + s = s.groups()[0] + if s[0] == "#": + s = s[1:] + if s[0] in ['x','X']: + c = int(s[1:], 16) + else: + c = int(s) + return unichr(c) + else: + # Cannot use name2codepoint directly, because HTMLParser supports apos, + # which is not part of HTML 4 + import htmlentitydefs + if HTMLParser.entitydefs is None: + entitydefs = HTMLParser.entitydefs = {'apos':u"'"} + for k, v in htmlentitydefs.name2codepoint.items(): + entitydefs[k] = unichr(v) + try: + return self.entitydefs[s] + except KeyError: + return '&'+s+';' + + return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));", replaceEntities, s) Modified: python/branches/p3yk/Lib/SimpleXMLRPCServer.py ============================================================================== --- python/branches/p3yk/Lib/SimpleXMLRPCServer.py (original) +++ python/branches/p3yk/Lib/SimpleXMLRPCServer.py Fri Apr 27 21:54:29 2007 @@ -517,11 +517,11 @@ allow_reuse_address = True def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, - logRequests=True, allow_none=False, encoding=None): + logRequests=True, allow_none=False, encoding=None, bind_and_activate=True): self.logRequests = logRequests SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) - SocketServer.TCPServer.__init__(self, addr, requestHandler) + SocketServer.TCPServer.__init__(self, addr, requestHandler, bind_and_activate) # [Bug #1222790] If possible, set close-on-exec flag; if a # method spawns a subprocess, the subprocess shouldn't have Modified: python/branches/p3yk/Lib/SocketServer.py ============================================================================== --- python/branches/p3yk/Lib/SocketServer.py (original) +++ python/branches/p3yk/Lib/SocketServer.py Fri Apr 27 21:54:29 2007 @@ -279,7 +279,7 @@ Methods for the caller: - - __init__(server_address, RequestHandlerClass) + - __init__(server_address, RequestHandlerClass, bind_and_activate=True) - serve_forever() - handle_request() # if you don't use serve_forever() - fileno() -> int # for select() @@ -322,13 +322,14 @@ allow_reuse_address = False - def __init__(self, server_address, RequestHandlerClass): + def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): """Constructor. May be extended, do not override.""" BaseServer.__init__(self, server_address, RequestHandlerClass) self.socket = socket.socket(self.address_family, self.socket_type) - self.server_bind() - self.server_activate() + if bind_and_activate: + self.server_bind() + self.server_activate() def server_bind(self): """Called by constructor to bind the socket. @@ -339,6 +340,7 @@ if self.allow_reuse_address: self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self.server_address) + self.server_address = self.socket.getsockname() def server_activate(self): """Called by constructor to activate the server. Modified: python/branches/p3yk/Lib/_strptime.py ============================================================================== --- python/branches/p3yk/Lib/_strptime.py (original) +++ python/branches/p3yk/Lib/_strptime.py Fri Apr 27 21:54:29 2007 @@ -295,17 +295,16 @@ """Return a time struct based on the input string and the format string.""" global _TimeRE_cache, _regex_cache with _cache_lock: - time_re = _TimeRE_cache - locale_time = time_re.locale_time - if _getlang() != locale_time.lang: + if _getlang() != _TimeRE_cache.locale_time.lang: _TimeRE_cache = TimeRE() - _regex_cache = {} + _regex_cache.clear() if len(_regex_cache) > _CACHE_MAX_SIZE: _regex_cache.clear() + locale_time = _TimeRE_cache.locale_time format_regex = _regex_cache.get(format) if not format_regex: try: - format_regex = time_re.compile(format) + format_regex = _TimeRE_cache.compile(format) # KeyError raised when a bad format is found; can be specified as # \\, in which case it was a stray % but with a space after it except KeyError as err: Modified: python/branches/p3yk/Lib/bisect.py ============================================================================== --- python/branches/p3yk/Lib/bisect.py (original) +++ python/branches/p3yk/Lib/bisect.py Fri Apr 27 21:54:29 2007 @@ -23,8 +23,8 @@ """Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e <= x, and all e in - a[i:] have e > x. So if x already appears in the list, i points just - beyond the rightmost x already there. + a[i:] have e > x. So if x already appears in the list, a.insert(x) will + insert just after the rightmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. @@ -62,8 +62,8 @@ """Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e < x, and all e in - a[i:] have e >= x. So if x already appears in the list, i points just - before the leftmost x already there. + a[i:] have e >= x. So if x already appears in the list, a.insert(x) will + insert just before the leftmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. Modified: python/branches/p3yk/Lib/cmd.py ============================================================================== --- python/branches/p3yk/Lib/cmd.py (original) +++ python/branches/p3yk/Lib/cmd.py Fri Apr 27 21:54:29 2007 @@ -49,11 +49,6 @@ PROMPT = '(Cmd) ' IDENTCHARS = string.ascii_letters + string.digits + '_' -def raw_input(prompt): - sys.stdout.write(prompt) - sys.stdout.flush() - return sys.stdin.readline() - class Cmd: """A simple framework for writing line-oriented command interpreters. @@ -129,7 +124,7 @@ else: if self.use_rawinput: try: - line = raw_input(self.prompt) + line = input(self.prompt) except EOFError: line = 'EOF' else: Copied: python/branches/p3yk/Lib/collections.py (from r54985, python/trunk/Lib/collections.py) ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/branches/p3yk/Lib/collections.py Fri Apr 27 21:54:29 2007 @@ -30,7 +30,7 @@ if kwds: try: args += tuple(kwds[name] for name in field_names[len(args):]) - except KeyError, name: + except KeyError as name: raise TypeError('%s missing required argument: %s' % (typename, name)) if len(args) != nargs: raise TypeError('%s takes exactly %d arguments (%d given)' % (typename, nargs, len(args))) @@ -59,4 +59,4 @@ import doctest TestResults = NamedTuple('TestResults', 'failed attempted') - print TestResults(*doctest.testmod()) + print(TestResults(*doctest.testmod())) Modified: python/branches/p3yk/Lib/commands.py ============================================================================== --- python/branches/p3yk/Lib/commands.py (original) +++ python/branches/p3yk/Lib/commands.py Fri Apr 27 21:54:29 2007 @@ -32,6 +32,8 @@ # def getstatus(file): """Return output of "ls -ld " in a string.""" + import warnings + warnings.warn("commands.getstatus() is deprecated", DeprecationWarning) return getoutput('ls -ld' + mkarg(file)) Modified: python/branches/p3yk/Lib/copy_reg.py ============================================================================== --- python/branches/p3yk/Lib/copy_reg.py (original) +++ python/branches/p3yk/Lib/copy_reg.py Fri Apr 27 21:54:29 2007 @@ -43,7 +43,8 @@ obj = object.__new__(cls) else: obj = base.__new__(cls, state) - base.__init__(obj, state) + if base.__init__ != object.__init__: + base.__init__(obj, state) return obj _HEAPTYPE = 1<<9 Modified: python/branches/p3yk/Lib/csv.py ============================================================================== --- python/branches/p3yk/Lib/csv.py (original) +++ python/branches/p3yk/Lib/csv.py Fri Apr 27 21:54:29 2007 @@ -115,9 +115,10 @@ def _dict_to_list(self, rowdict): if self.extrasaction == "raise": - for k in rowdict.keys(): - if k not in self.fieldnames: - raise ValueError, "dict contains fields not in fieldnames" + wrong_fields = [k for k in rowdict if k not in self.fieldnames] + if wrong_fields: + raise ValueError("dict contains fields not in fieldnames: " + + ", ".join(wrong_fields)) return [rowdict.get(key, self.restval) for key in self.fieldnames] def writerow(self, rowdict): Modified: python/branches/p3yk/Lib/ctypes/__init__.py ============================================================================== --- python/branches/p3yk/Lib/ctypes/__init__.py (original) +++ python/branches/p3yk/Lib/ctypes/__init__.py Fri Apr 27 21:54:29 2007 @@ -233,6 +233,9 @@ c_voidp = c_void_p # backwards compatibility (to a bug) _check_size(c_void_p) +class c_bool(_SimpleCData): + _type_ = "t" + # This cache maps types to pointers to them. _pointer_type_cache = {} @@ -480,7 +483,7 @@ return _cast(obj, obj, typ) _string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) -def string_at(ptr, size=0): +def string_at(ptr, size=-1): """string_at(addr[, size]) -> string Return the string at addr.""" @@ -492,7 +495,7 @@ pass else: _wstring_at = CFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) - def wstring_at(ptr, size=0): + def wstring_at(ptr, size=-1): """wstring_at(addr[, size]) -> string Return the string at addr.""" Modified: python/branches/p3yk/Lib/ctypes/test/test_functions.py ============================================================================== --- python/branches/p3yk/Lib/ctypes/test/test_functions.py (original) +++ python/branches/p3yk/Lib/ctypes/test/test_functions.py Fri Apr 27 21:54:29 2007 @@ -21,7 +21,9 @@ class POINT(Structure): _fields_ = [("x", c_int), ("y", c_int)] - +class RECT(Structure): + _fields_ = [("left", c_int), ("top", c_int), + ("right", c_int), ("bottom", c_int)] class FunctionTestCase(unittest.TestCase): def test_mro(self): @@ -379,5 +381,15 @@ self.failUnlessEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + def test_sf1651235(self): + # see http://www.python.org/sf/1651235 + + proto = CFUNCTYPE(c_int, RECT, POINT) + def callback(*args): + return 0 + + callback = proto(callback) + self.failUnlessRaises(ArgumentError, lambda: callback((1, 2, 3, 4), POINT())) + if __name__ == '__main__': unittest.main() Modified: python/branches/p3yk/Lib/ctypes/test/test_memfunctions.py ============================================================================== --- python/branches/p3yk/Lib/ctypes/test/test_memfunctions.py (original) +++ python/branches/p3yk/Lib/ctypes/test/test_memfunctions.py Fri Apr 27 21:54:29 2007 @@ -14,6 +14,7 @@ self.failUnlessEqual(string_at(result), "Hello, World") self.failUnlessEqual(string_at(result, 5), "Hello") self.failUnlessEqual(string_at(result, 16), "Hello, World\0\0\0\0") + self.failUnlessEqual(string_at(result, 0), "") def test_memset(self): a = create_string_buffer(1000000) @@ -54,6 +55,7 @@ self.failUnlessEqual(wstring_at(a), "Hello, World") self.failUnlessEqual(wstring_at(a, 5), "Hello") self.failUnlessEqual(wstring_at(a, 16), "Hello, World\0\0\0\0") + self.failUnlessEqual(wstring_at(a, 0), "") if __name__ == "__main__": unittest.main() Modified: python/branches/p3yk/Lib/ctypes/test/test_numbers.py ============================================================================== --- python/branches/p3yk/Lib/ctypes/test/test_numbers.py (original) +++ python/branches/p3yk/Lib/ctypes/test/test_numbers.py Fri Apr 27 21:54:29 2007 @@ -24,6 +24,8 @@ unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong] signed_types = [c_byte, c_short, c_int, c_long, c_longlong] +bool_types = [] + float_types = [c_double, c_float] try: @@ -35,8 +37,16 @@ unsigned_types.append(c_ulonglong) signed_types.append(c_longlong) +try: + c_bool +except NameError: + pass +else: + bool_types.append(c_bool) + unsigned_ranges = valid_ranges(*unsigned_types) signed_ranges = valid_ranges(*signed_types) +bool_values = [True, False, 0, 1, -1, 5000, 'test', [], [1]] ################################################################ @@ -60,6 +70,11 @@ self.failUnlessEqual(t(l).value, l) self.failUnlessEqual(t(h).value, h) + def test_bool_values(self): + from operator import truth + for t, v in zip(bool_types, bool_values): + self.failUnlessEqual(t(v).value, truth(v)) + def test_typeerror(self): # Only numbers are allowed in the contructor, # otherwise TypeError is raised @@ -82,7 +97,7 @@ def test_byref(self): # calling byref returns also a PyCArgObject instance - for t in signed_types + unsigned_types + float_types: + for t in signed_types + unsigned_types + float_types + bool_types: parm = byref(t()) self.failUnlessEqual(ArgType, type(parm)) @@ -101,7 +116,7 @@ self.assertRaises(TypeError, t, 3.14) def test_sizes(self): - for t in signed_types + unsigned_types + float_types: + for t in signed_types + unsigned_types + float_types + bool_types: size = struct.calcsize(t._type_) # sizeof of the type... self.failUnlessEqual(sizeof(t), size) @@ -164,6 +179,18 @@ a[0] = '?' self.failUnlessEqual(v.value, a[0]) + # array does not support c_bool / 't' + # def test_bool_from_address(self): + # from ctypes import c_bool + # from array import array + # a = array(c_bool._type_, [True]) + # v = t.from_address(a.buffer_info()[0]) + # self.failUnlessEqual(v.value, a[0]) + # self.failUnlessEqual(type(v) is t) + # a[0] = False + # self.failUnlessEqual(v.value, a[0]) + # self.failUnlessEqual(type(v) is t) + def test_init(self): # c_int() can be initialized from Python's int, and c_int. # Not from c_long or so, which seems strange, abd should Modified: python/branches/p3yk/Lib/ctypes/test/test_repr.py ============================================================================== --- python/branches/p3yk/Lib/ctypes/test/test_repr.py (original) +++ python/branches/p3yk/Lib/ctypes/test/test_repr.py Fri Apr 27 21:54:29 2007 @@ -4,7 +4,7 @@ subclasses = [] for base in [c_byte, c_short, c_int, c_long, c_longlong, c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong, - c_float, c_double]: + c_float, c_double, c_bool]: class X(base): pass subclasses.append(X) Modified: python/branches/p3yk/Lib/decimal.py ============================================================================== --- python/branches/p3yk/Lib/decimal.py (original) +++ python/branches/p3yk/Lib/decimal.py Fri Apr 27 21:54:29 2007 @@ -29,8 +29,8 @@ Decimal floating point has finite precision with arbitrarily large bounds. -The purpose of the module is to support arithmetic using familiar -"schoolhouse" rules and to avoid the some of tricky representation +The purpose of this module is to support arithmetic using familiar +"schoolhouse" rules and to avoid some of the tricky representation issues associated with binary floating point. The package is especially useful for financial applications or for contexts where users have expectations that are at odds with binary floating point (for instance, @@ -136,7 +136,7 @@ import copy as _copy -#Rounding +# Rounding ROUND_DOWN = 'ROUND_DOWN' ROUND_HALF_UP = 'ROUND_HALF_UP' ROUND_HALF_EVEN = 'ROUND_HALF_EVEN' @@ -145,11 +145,11 @@ ROUND_UP = 'ROUND_UP' ROUND_HALF_DOWN = 'ROUND_HALF_DOWN' -#Rounding decision (not part of the public API) +# Rounding decision (not part of the public API) NEVER_ROUND = 'NEVER_ROUND' # Round in division (non-divmod), sqrt ONLY ALWAYS_ROUND = 'ALWAYS_ROUND' # Every operation rounds at end. -#Errors +# Errors class DecimalException(ArithmeticError): """Base exception class. @@ -179,9 +179,9 @@ This occurs and signals clamped if the exponent of a result has been altered in order to fit the constraints of a specific concrete - representation. This may occur when the exponent of a zero result would - be outside the bounds of a representation, or when a large normal - number would have an encoded exponent that cannot be represented. In + representation. This may occur when the exponent of a zero result would + be outside the bounds of a representation, or when a large normal + number would have an encoded exponent that cannot be represented. In this latter case, the exponent is reduced to fit and the corresponding number of zero digits are appended to the coefficient ("fold-down"). """ @@ -194,8 +194,8 @@ Something creates a signaling NaN -INF + INF - 0 * (+-)INF - (+-)INF / (+-)INF + 0 * (+-)INF + (+-)INF / (+-)INF x % 0 (+-)INF % x x._rescale( non-integer ) @@ -207,7 +207,7 @@ """ def handle(self, context, *args): if args: - if args[0] == 1: #sNaN, must drop 's' but keep diagnostics + if args[0] == 1: # sNaN, must drop 's' but keep diagnostics return Decimal( (args[1]._sign, args[1]._int, 'n') ) return NaN @@ -216,11 +216,11 @@ This occurs and signals invalid-operation if an string is being converted to a number and it does not conform to the numeric string - syntax. The result is [0,qNaN]. + syntax. The result is [0,qNaN]. """ def handle(self, context, *args): - return (0, (0,), 'n') #Passed to something which uses a tuple. + return (0, (0,), 'n') # Passed to something which uses a tuple. class DivisionByZero(DecimalException, ZeroDivisionError): """Division by 0. @@ -245,7 +245,7 @@ This occurs and signals invalid-operation if the integer result of a divide-integer or remainder operation had too many digits (would be - longer than precision). The result is [0,qNaN]. + longer than precision). The result is [0,qNaN]. """ def handle(self, context, *args): @@ -256,12 +256,12 @@ This occurs and signals invalid-operation if division by zero was attempted (during a divide-integer, divide, or remainder operation), and - the dividend is also zero. The result is [0,qNaN]. + the dividend is also zero. The result is [0,qNaN]. """ def handle(self, context, tup=None, *args): if tup is not None: - return (NaN, NaN) #for 0 %0, 0 // 0 + return (NaN, NaN) # for 0 %0, 0 // 0 return NaN class Inexact(DecimalException): @@ -269,7 +269,7 @@ This occurs and signals inexact whenever the result of an operation is not exact (that is, it needed to be rounded and any discarded digits - were non-zero), or if an overflow or underflow condition occurs. The + were non-zero), or if an overflow or underflow condition occurs. The result in all cases is unchanged. The inexact signal may be tested (or trapped) to determine if a given @@ -281,11 +281,11 @@ """Invalid context. Unknown rounding, for example. This occurs and signals invalid-operation if an invalid context was - detected during an operation. This can occur if contexts are not checked + detected during an operation. This can occur if contexts are not checked on creation and either the precision exceeds the capability of the underlying concrete representation or an unknown or unsupported rounding - was specified. These aspects of the context need only be checked when - the values are required to be used. The result is [0,qNaN]. + was specified. These aspects of the context need only be checked when + the values are required to be used. The result is [0,qNaN]. """ def handle(self, context, *args): @@ -296,7 +296,7 @@ This occurs and signals rounded whenever the result of an operation is rounded (that is, some zero or non-zero digits were discarded from the - coefficient), or if an overflow or underflow condition occurs. The + coefficient), or if an overflow or underflow condition occurs. The result in all cases is unchanged. The rounded signal may be tested (or trapped) to determine if a given @@ -309,7 +309,7 @@ This occurs and signals subnormal whenever the result of a conversion or operation is subnormal (that is, its adjusted exponent is less than - Emin, before any rounding). The result in all cases is unchanged. + Emin, before any rounding). The result in all cases is unchanged. The subnormal signal may be tested (or trapped) to determine if a given or operation (or sequence of operations) yielded a subnormal result. @@ -328,13 +328,13 @@ For round-half-up and round-half-even (and for round-half-down and round-up, if implemented), the result of the operation is [sign,inf], - where sign is the sign of the intermediate result. For round-down, the + where sign is the sign of the intermediate result. For round-down, the result is the largest finite number that can be represented in the - current precision, with the sign of the intermediate result. For + current precision, with the sign of the intermediate result. For round-ceiling, the result is the same as for round-down if the sign of - the intermediate result is 1, or is [0,inf] otherwise. For round-floor, + the intermediate result is 1, or is [0,inf] otherwise. For round-floor, the result is the same as for round-down if the sign of the intermediate - result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded + result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded will also be raised. """ @@ -360,10 +360,10 @@ This occurs and signals underflow if a result is inexact and the adjusted exponent of the result would be smaller (more negative) than the smallest value that can be handled by the implementation (the value - Emin). That is, the result is both inexact and subnormal. + Emin). That is, the result is both inexact and subnormal. The result after an underflow will be a subnormal number rounded, if - necessary, so that its exponent is not less than Etiny. This may result + necessary, so that its exponent is not less than Etiny. This may result in 0 with the sign of the intermediate result and an exponent of Etiny. In all cases, Inexact, Rounded, and Subnormal will also be raised. @@ -379,7 +379,7 @@ DivisionUndefined:InvalidOperation, InvalidContext:InvalidOperation} -##### Context Functions ####################################### +##### Context Functions ################################################## # The getcontext() and setcontext() function manage access to a thread-local # current context. Py2.4 offers direct support for thread locals. If that @@ -392,7 +392,7 @@ except ImportError: # Python was compiled without threads; create a mock object instead import sys - class MockThreading: + class MockThreading(object): def local(self, sys=sys): return sys.modules[__name__] threading = MockThreading() @@ -403,8 +403,8 @@ except AttributeError: - #To fix reloading, force it to create a new context - #Old contexts have different exceptions in their dicts, making problems. + # To fix reloading, force it to create a new context + # Old contexts have different exceptions in their dicts, making problems. if hasattr(threading.currentThread(), '__decimal_context__'): del threading.currentThread().__decimal_context__ @@ -469,14 +469,14 @@ ctx.prec += 2 # Rest of sin calculation algorithm # uses a precision 2 greater than normal - return +s # Convert result to normal precision + return +s # Convert result to normal precision def sin(x): with localcontext(ExtendedContext): # Rest of sin calculation algorithm # uses the Extended Context from the # General Decimal Arithmetic Specification - return +s # Convert result to normal context + return +s # Convert result to normal context """ # The string below can't be included in the docstring until Python 2.6 @@ -489,11 +489,11 @@ ... ctx = getcontext() ... ctx.prec += 2 ... print(ctx.prec) - ... + ... 30 >>> with localcontext(ExtendedContext): ... print(getcontext().prec) - ... + ... 9 >>> print(getcontext().prec) 28 @@ -502,7 +502,7 @@ return _ContextManager(ctx) -##### Decimal class ########################################### +##### Decimal class ####################################################### class Decimal(object): """Floating point class for decimal arithmetic.""" @@ -518,7 +518,7 @@ >>> Decimal('3.14') # string input Decimal("3.14") - >>> Decimal((0, (3, 1, 4), -2)) # tuple input (sign, digit_tuple, exponent) + >>> Decimal((0, (3, 1, 4), -2)) # tuple (sign, digit_tuple, exponent) Decimal("3.14") >>> Decimal(314) # int or long Decimal("314") @@ -557,13 +557,13 @@ # tuple/list conversion (possibly from as_tuple()) if isinstance(value, (list,tuple)): if len(value) != 3: - raise ValueError, 'Invalid arguments' + raise ValueError('Invalid arguments') if value[0] not in (0,1): - raise ValueError, 'Invalid sign' + raise ValueError('Invalid sign') for digit in value[1]: if not isinstance(digit, (int,int)) or digit < 0: - raise ValueError, "The second value in the tuple must be composed of non negative integer elements." - + raise ValueError("The second value in the tuple must be" + "composed of non negative integer elements.") self._sign = value[0] self._int = tuple(value[1]) if value[2] in ('F','n','N'): @@ -596,22 +596,23 @@ if _isnan(value): sig, sign, diag = _isnan(value) self._is_special = True - if len(diag) > context.prec: #Diagnostic info too long + if len(diag) > context.prec: # Diagnostic info too long self._sign, self._int, self._exp = \ context._raise_error(ConversionSyntax) return self if sig == 1: - self._exp = 'n' #qNaN - else: #sig == 2 - self._exp = 'N' #sNaN + self._exp = 'n' # qNaN + else: # sig == 2 + self._exp = 'N' # sNaN self._sign = sign - self._int = tuple(map(int, diag)) #Diagnostic info + self._int = tuple(map(int, diag)) # Diagnostic info return self try: self._sign, self._int, self._exp = _string2exact(value) except ValueError: self._is_special = True - self._sign, self._int, self._exp = context._raise_error(ConversionSyntax) + self._sign, self._int, self._exp = \ + context._raise_error(ConversionSyntax) return self raise TypeError("Cannot convert %r to Decimal" % value) @@ -694,15 +695,15 @@ if self._is_special or other._is_special: ans = self._check_nans(other, context) if ans: - return 1 # Comparison involving NaN's always reports self > other + return 1 # Comparison involving NaN's always reports self > other # INF = INF return cmp(self._isinfinity(), other._isinfinity()) if not self and not other: - return 0 #If both 0, sign comparison isn't certain. + return 0 # If both 0, sign comparison isn't certain. - #If different signs, neg one is less + # If different signs, neg one is less if other._sign < self._sign: return -1 if self._sign < other._sign: @@ -713,7 +714,7 @@ if self_adjusted == other_adjusted and \ self._int + (0,)*(self._exp - other._exp) == \ other._int + (0,)*(other._exp - self._exp): - return 0 #equal, except in precision. ([0]*(-x) = []) + return 0 # equal, except in precision. ([0]*(-x) = []) elif self_adjusted > other_adjusted and self._int[0] != 0: return (-1)**self._sign elif self_adjusted < other_adjusted and other._int[0] != 0: @@ -724,7 +725,7 @@ context = getcontext() context = context._shallow_copy() - rounding = context._set_rounding(ROUND_UP) #round away from 0 + rounding = context._set_rounding(ROUND_UP) # round away from 0 flags = context._ignore_all_flags() res = self.__sub__(other, context=context) @@ -782,7 +783,7 @@ if other is NotImplemented: return other - #compare(NaN, NaN) = NaN + # Compare(NaN, NaN) = NaN if (self._is_special or other and other._is_special): ans = self._check_nans(other, context) if ans: @@ -843,11 +844,11 @@ tmp = map(str, self._int) numdigits = len(self._int) leftdigits = self._exp + numdigits - if eng and not self: #self = 0eX wants 0[.0[0]]eY, not [[0]0]0eY - if self._exp < 0 and self._exp >= -6: #short, no need for e/E + if eng and not self: # self = 0eX wants 0[.0[0]]eY, not [[0]0]0eY + if self._exp < 0 and self._exp >= -6: # short, no need for e/E s = '-'*self._sign + '0.' + '0'*(abs(self._exp)) return s - #exp is closest mult. of 3 >= self._exp + # exp is closest mult. of 3 >= self._exp exp = ((self._exp - 1)// 3 + 1) * 3 if exp != self._exp: s = '0.'+'0'*(exp - self._exp) @@ -859,7 +860,7 @@ else: s += 'e' if exp > 0: - s += '+' #0.0e+3, not 0.0e3 + s += '+' # 0.0e+3, not 0.0e3 s += str(exp) s = '-'*self._sign + s return s @@ -999,19 +1000,19 @@ return ans if self._isinfinity(): - #If both INF, same sign => same as both, opposite => error. + # If both INF, same sign => same as both, opposite => error. if self._sign != other._sign and other._isinfinity(): return context._raise_error(InvalidOperation, '-INF + INF') return Decimal(self) if other._isinfinity(): - return Decimal(other) #Can't both be infinity here + return Decimal(other) # Can't both be infinity here shouldround = context._rounding_decision == ALWAYS_ROUND exp = min(self._exp, other._exp) negativezero = 0 if context.rounding == ROUND_FLOOR and self._sign != other._sign: - #If the answer is 0, the sign should be negative, in this case. + # If the answer is 0, the sign should be negative, in this case. negativezero = 1 if not self and not other: @@ -1046,19 +1047,19 @@ return Decimal((negativezero, (0,), exp)) if op1.int < op2.int: op1, op2 = op2, op1 - #OK, now abs(op1) > abs(op2) + # OK, now abs(op1) > abs(op2) if op1.sign == 1: result.sign = 1 op1.sign, op2.sign = op2.sign, op1.sign else: result.sign = 0 - #So we know the sign, and op1 > 0. + # So we know the sign, and op1 > 0. elif op1.sign == 1: result.sign = 1 op1.sign, op2.sign = (0, 0) else: result.sign = 0 - #Now, op1 > abs(op2) > 0 + # Now, op1 > abs(op2) > 0 if op2.sign == 0: result.int = op1.int + op2.int @@ -1116,7 +1117,8 @@ if ans: return ans - return Decimal(self) # Must be infinite, and incrementing makes no difference + # Must be infinite, and incrementing makes no difference + return Decimal(self) L = list(self._int) L[-1] += 1 @@ -1172,7 +1174,7 @@ if not self or not other: ans = Decimal((resultsign, (0,), resultexp)) if shouldround: - #Fixing in case the exponent is out of bounds + # Fixing in case the exponent is out of bounds ans = ans._fix(context) return ans @@ -1191,7 +1193,7 @@ op1 = _WorkRep(self) op2 = _WorkRep(other) - ans = Decimal( (resultsign, map(int, str(op1.int * op2.int)), resultexp)) + ans = Decimal((resultsign, map(int, str(op1.int * op2.int)), resultexp)) if shouldround: ans = ans._fix(context) @@ -1283,12 +1285,11 @@ sign, 1) return context._raise_error(DivisionByZero, 'x / 0', sign) - #OK, so neither = 0, INF or NaN - + # OK, so neither = 0, INF or NaN shouldround = context._rounding_decision == ALWAYS_ROUND - #If we're dividing into ints, and self < other, stop. - #self.__abs__(0) does not round. + # If we're dividing into ints, and self < other, stop. + # self.__abs__(0) does not round. if divmod and (self.__abs__(0, context) < other.__abs__(0, context)): if divmod == 1 or divmod == 3: @@ -1300,7 +1301,7 @@ ans2) elif divmod == 2: - #Don't round the mod part, if we don't need it. + # Don't round the mod part, if we don't need it. return (Decimal( (sign, (0,), 0) ), Decimal(self)) op1 = _WorkRep(self) @@ -1349,7 +1350,7 @@ op1.exp -= 1 if res.exp == 0 and divmod and op2.int > op1.int: - #Solves an error in precision. Same as a previous block. + # Solves an error in precision. Same as a previous block. if res.int >= prec_limit and shouldround: return context._raise_error(DivisionImpossible) @@ -1434,7 +1435,7 @@ # ignored in the calling function. context = context._shallow_copy() flags = context._ignore_flags(Rounded, Inexact) - #keep DivisionImpossible flags + # Keep DivisionImpossible flags (side, r) = self.__divmod__(other, context=context) if r._isnan(): @@ -1457,7 +1458,7 @@ if r < comparison: r._sign, comparison._sign = s1, s2 - #Get flags now + # Get flags now self.__divmod__(other, context=context) return r._fix(context) r._sign, comparison._sign = s1, s2 @@ -1479,7 +1480,8 @@ if r > comparison or decrease and r == comparison: r._sign, comparison._sign = s1, s2 context.prec += 1 - if len(side.__add__(Decimal(1), context=context)._int) >= context.prec: + numbsquant = len(side.__add__(Decimal(1), context=context)._int) + if numbsquant >= context.prec: context.prec -= 1 return context._raise_error(DivisionImpossible)[1] context.prec -= 1 @@ -1514,7 +1516,7 @@ context = getcontext() return context._raise_error(InvalidContext) elif self._isinfinity(): - raise OverflowError, "Cannot convert infinity to long" + raise OverflowError("Cannot convert infinity to long") if self._exp >= 0: s = ''.join(map(str, self._int)) + '0'*self._exp else: @@ -1568,13 +1570,13 @@ context._raise_error(Clamped) return ans ans = ans._rescale(Etiny, context=context) - #It isn't zero, and exp < Emin => subnormal + # It isn't zero, and exp < Emin => subnormal context._raise_error(Subnormal) if context.flags[Inexact]: context._raise_error(Underflow) else: if ans: - #Only raise subnormal if non-zero. + # Only raise subnormal if non-zero. context._raise_error(Subnormal) else: Etop = context.Etop() @@ -1591,7 +1593,8 @@ return ans context._raise_error(Inexact) context._raise_error(Rounded) - return context._raise_error(Overflow, 'above Emax', ans._sign) + c = context._raise_error(Overflow, 'above Emax', ans._sign) + return c return ans def _round(self, prec=None, rounding=None, context=None): @@ -1651,18 +1654,18 @@ ans = Decimal( (temp._sign, tmp, temp._exp - expdiff)) return ans - #OK, but maybe all the lost digits are 0. + # OK, but maybe all the lost digits are 0. lostdigits = self._int[expdiff:] if lostdigits == (0,) * len(lostdigits): ans = Decimal( (temp._sign, temp._int[:prec], temp._exp - expdiff)) - #Rounded, but not Inexact + # Rounded, but not Inexact context._raise_error(Rounded) return ans # Okay, let's round and lose data this_function = getattr(temp, self._pick_rounding_function[rounding]) - #Now we've got the rounding function + # Now we've got the rounding function if prec != context.prec: context = context._shallow_copy() @@ -1758,7 +1761,7 @@ context = getcontext() if self._is_special or n._is_special or n.adjusted() > 8: - #Because the spot << doesn't work with really big exponents + # Because the spot << doesn't work with really big exponents if n._isinfinity() or n.adjusted() > 8: return context._raise_error(InvalidOperation, 'x ** INF') @@ -1788,9 +1791,10 @@ return Infsign[sign] return Decimal( (sign, (0,), 0) ) - #with ludicrously large exponent, just raise an overflow and return inf. - if not modulo and n > 0 and (self._exp + len(self._int) - 1) * n > context.Emax \ - and self: + # With ludicrously large exponent, just raise an overflow + # and return inf. + if not modulo and n > 0 and \ + (self._exp + len(self._int) - 1) * n > context.Emax and self: tmp = Decimal('inf') tmp._sign = sign @@ -1810,7 +1814,7 @@ context = context._shallow_copy() context.prec = firstprec + elength + 1 if n < 0: - #n is a long now, not Decimal instance + # n is a long now, not Decimal instance n = -n mul = Decimal(1).__truediv__(mul, context=context) @@ -1819,7 +1823,7 @@ spot <<= 1 spot >>= 1 - #Spot is the highest power of 2 less than n + # spot is the highest power of 2 less than n while spot: val = val.__mul__(val, context=context) if val._isinfinity(): @@ -1877,7 +1881,7 @@ if exp._isinfinity() or self._isinfinity(): if exp._isinfinity() and self._isinfinity(): - return self #if both are inf, it is OK + return self # if both are inf, it is OK if context is None: context = getcontext() return context._raise_error(InvalidOperation, @@ -1982,13 +1986,13 @@ return Decimal(self) if not self: - #exponent = self._exp / 2, using round_down. - #if self._exp < 0: + # exponent = self._exp / 2, using round_down. + # if self._exp < 0: # exp = (self._exp+1) // 2 - #else: + # else: exp = (self._exp) // 2 if self._sign == 1: - #sqrt(-0) = -0 + # sqrt(-0) = -0 return Decimal( (1, (0,), exp)) else: return Decimal( (0, (0,), exp)) @@ -2023,8 +2027,7 @@ context=context), context=context) ans._exp -= 1 + tmp.adjusted() // 2 - #ans is now a linear approximation. - + # ans is now a linear approximation. Emax, Emin = context.Emax, context.Emin context.Emax, context.Emin = DefaultContext.Emax, DefaultContext.Emin @@ -2039,12 +2042,12 @@ if context.prec == maxp: break - #round to the answer's precision-- the only error can be 1 ulp. + # Round to the answer's precision-- the only error can be 1 ulp. context.prec = firstprec prevexp = ans.adjusted() ans = ans._round(context=context) - #Now, check if the other last digits are better. + # Now, check if the other last digits are better. context.prec = firstprec + 1 # In case we rounded up another digit and we should actually go lower. if prevexp != ans.adjusted(): @@ -2076,10 +2079,10 @@ context._raise_error(Rounded) context._raise_error(Inexact) else: - #Exact answer, so let's set the exponent right. - #if self._exp < 0: + # Exact answer, so let's set the exponent right. + # if self._exp < 0: # exp = (self._exp +1)// 2 - #else: + # else: exp = self._exp // 2 context.prec += ans._exp - exp ans = ans._rescale(exp, context=context) @@ -2100,7 +2103,7 @@ return other if self._is_special or other._is_special: - # if one operand is a quiet NaN and the other is number, then the + # If one operand is a quiet NaN and the other is number, then the # number is always returned sn = self._isnan() on = other._isnan() @@ -2114,13 +2117,13 @@ ans = self c = self.__cmp__(other) if c == 0: - # if both operands are finite and equal in numerical value + # If both operands are finite and equal in numerical value # then an ordering is applied: # - # if the signs differ then max returns the operand with the + # If the signs differ then max returns the operand with the # positive sign and min returns the operand with the negative sign # - # if the signs are the same then the exponent is used to select + # If the signs are the same then the exponent is used to select # the result. if self._sign != other._sign: if self._sign: @@ -2141,7 +2144,7 @@ def min(self, other, context=None): """Returns the smaller value. - like min(self, other) except if one is not a number, returns + Like min(self, other) except if one is not a number, returns NaN (and signals if one is sNaN). Also rounds. """ other = _convert_other(other) @@ -2149,7 +2152,7 @@ return other if self._is_special or other._is_special: - # if one operand is a quiet NaN and the other is number, then the + # If one operand is a quiet NaN and the other is number, then the # number is always returned sn = self._isnan() on = other._isnan() @@ -2163,13 +2166,13 @@ ans = self c = self.__cmp__(other) if c == 0: - # if both operands are finite and equal in numerical value + # If both operands are finite and equal in numerical value # then an ordering is applied: # - # if the signs differ then max returns the operand with the + # If the signs differ then max returns the operand with the # positive sign and min returns the operand with the negative sign # - # if the signs are the same then the exponent is used to select + # If the signs are the same then the exponent is used to select # the result. if self._sign != other._sign: if other._sign: @@ -2204,11 +2207,11 @@ """Return the adjusted exponent of self""" try: return self._exp + len(self._int) - 1 - #If NaN or Infinity, self._exp is string + # If NaN or Infinity, self._exp is string except TypeError: return 0 - # support for pickling, copy, and deepcopy + # Support for pickling, copy, and deepcopy def __reduce__(self): return (self.__class__, (str(self),)) @@ -2222,13 +2225,14 @@ return self # My components are also immutable return self.__class__(str(self)) -##### Context class ########################################### +##### Context class ####################################################### # get rounding method function: -rounding_functions = [name for name in Decimal.__dict__.keys() if name.startswith('_round_')] +rounding_functions = [name for name in Decimal.__dict__.keys() + if name.startswith('_round_')] for name in rounding_functions: - #name is like _round_half_even, goes to the global ROUND_HALF_EVEN value. + # name is like _round_half_even, goes to the global ROUND_HALF_EVEN value. globalname = name[1:].upper() val = globals()[globalname] Decimal._pick_rounding_function[val] = name @@ -2255,7 +2259,7 @@ Contains: prec - precision (for use in rounding, division, square roots..) - rounding - rounding type. (how you round) + rounding - rounding type (how you round) _rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do you round? traps - If traps[exception] = 1, then the exception is raised when it is caused. Otherwise, a value is @@ -2294,9 +2298,13 @@ def __repr__(self): """Show the current context.""" s = [] - s.append('Context(prec=%(prec)d, rounding=%(rounding)s, Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d' % vars(self)) - s.append('flags=[' + ', '.join([f.__name__ for f, v in self.flags.items() if v]) + ']') - s.append('traps=[' + ', '.join([t.__name__ for t, v in self.traps.items() if v]) + ']') + s.append('Context(prec=%(prec)d, rounding=%(rounding)s, ' + 'Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d' + % vars(self)) + names = [f.__name__ for f, v in self.flags.items() if v] + s.append('flags=[' + ', '.join(names) + ']') + names = [t.__name__ for t, v in self.traps.items() if v] + s.append('traps=[' + ', '.join(names) + ']') return ', '.join(s) + ')' def clear_flags(self): @@ -2313,9 +2321,9 @@ def copy(self): """Returns a deep copy from self.""" - nc = Context(self.prec, self.rounding, self.traps.copy(), self.flags.copy(), - self._rounding_decision, self.Emin, self.Emax, - self.capitals, self._clamp, self._ignored_flags) + nc = Context(self.prec, self.rounding, self.traps.copy(), + self.flags.copy(), self._rounding_decision, self.Emin, + self.Emax, self.capitals, self._clamp, self._ignored_flags) return nc __copy__ = copy @@ -2329,16 +2337,16 @@ """ error = _condition_map.get(condition, condition) if error in self._ignored_flags: - #Don't touch the flag + # Don't touch the flag return error().handle(self, *args) self.flags[error] += 1 if not self.traps[error]: - #The errors define how to handle themselves. + # The errors define how to handle themselves. return condition().handle(self, *args) # Errors should only be risked on copies of the context - #self._ignored_flags = [] + # self._ignored_flags = [] raise error, explanation def _ignore_all_flags(self): @@ -2362,7 +2370,7 @@ def __hash__(self): """A Context cannot be hashed.""" # We inherit object.__hash__, so we must deny this explicitly - raise TypeError, "Cannot hash a Context." + raise TypeError("Cannot hash a Context.") def Etiny(self): """Returns Etiny (= Emin - prec + 1)""" @@ -2417,12 +2425,12 @@ d = Decimal(num, context=self) return d._fix(self) - #Methods + # Methods def abs(self, a): """Returns the absolute value of the operand. If the operand is negative, the result is the same as using the minus - operation on the operand. Otherwise, the result is the same as using + operation on the operand. Otherwise, the result is the same as using the plus operation on the operand. >>> ExtendedContext.abs(Decimal('2.1')) @@ -2524,8 +2532,8 @@ If either operand is a NaN then the general rules apply. Otherwise, the operands are compared as as though by the compare - operation. If they are numerically equal then the left-hand operand - is chosen as the result. Otherwise the maximum (closer to positive + operation. If they are numerically equal then the left-hand operand + is chosen as the result. Otherwise the maximum (closer to positive infinity) of the two operands is chosen as the result. >>> ExtendedContext.max(Decimal('3'), Decimal('2')) @@ -2544,8 +2552,8 @@ If either operand is a NaN then the general rules apply. Otherwise, the operands are compared as as though by the compare - operation. If they are numerically equal then the left-hand operand - is chosen as the result. Otherwise the minimum (closer to negative + operation. If they are numerically equal then the left-hand operand + is chosen as the result. Otherwise the minimum (closer to negative infinity) of the two operands is chosen as the result. >>> ExtendedContext.min(Decimal('3'), Decimal('2')) @@ -2634,14 +2642,14 @@ The right-hand operand must be a whole number whose integer part (after any exponent has been applied) has no more than 9 digits and whose - fractional part (if any) is all zeros before any rounding. The operand + fractional part (if any) is all zeros before any rounding. The operand may be positive, negative, or zero; if negative, the absolute value of the power is used, and the left-hand operand is inverted (divided into 1) before use. If the increased precision needed for the intermediate calculations - exceeds the capabilities of the implementation then an Invalid operation - condition is raised. + exceeds the capabilities of the implementation then an Invalid + operation condition is raised. If, when raising to a negative power, an underflow occurs during the division into 1, the operation is not halted at that point but @@ -2679,18 +2687,18 @@ return a.__pow__(b, modulo, context=self) def quantize(self, a, b): - """Returns a value equal to 'a' (rounded) and having the exponent of 'b'. + """Returns a value equal to 'a' (rounded), having the exponent of 'b'. The coefficient of the result is derived from that of the left-hand - operand. It may be rounded using the current rounding setting (if the + operand. It may be rounded using the current rounding setting (if the exponent is being increased), multiplied by a positive power of ten (if the exponent is being decreased), or is unchanged (if the exponent is already equal to that of the right-hand operand). Unlike other operations, if the length of the coefficient after the quantize operation would be greater than precision then an Invalid - operation condition is raised. This guarantees that, unless there is an - error condition, the exponent of the result of a quantize is always + operation condition is raised. This guarantees that, unless there is + an error condition, the exponent of the result of a quantize is always equal to that of the right-hand operand. Also unlike other operations, quantize will never raise Underflow, even @@ -2733,9 +2741,9 @@ """Returns the remainder from integer division. The result is the residue of the dividend after the operation of - calculating integer division as described for divide-integer, rounded to - precision digits if necessary. The sign of the result, if non-zero, is - the same as that of the original dividend. + calculating integer division as described for divide-integer, rounded + to precision digits if necessary. The sign of the result, if + non-zero, is the same as that of the original dividend. This operation will fail under the same conditions as integer division (that is, if integer division on the same two operands would fail, the @@ -2759,7 +2767,7 @@ def remainder_near(self, a, b): """Returns to be "a - b * n", where n is the integer nearest the exact value of "x / b" (if two integers are equally near then the even one - is chosen). If the result is equal to 0 then its sign will be the + is chosen). If the result is equal to 0 then its sign will be the sign of a. This operation will fail under the same conditions as integer division @@ -2801,7 +2809,7 @@ return a.same_quantum(b) def sqrt(self, a): - """Returns the square root of a non-negative number to context precision. + """Square root of a non-negative number to context precision. If the result must be inexact, it is rounded using the round-half-even algorithm. @@ -2862,7 +2870,7 @@ as using the quantize() operation using the given operand as the left-hand-operand, 1E+0 as the right-hand-operand, and the precision of the operand as the precision setting, except that no flags will - be set. The rounding mode is taken from the context. + be set. The rounding mode is taken from the context. >>> ExtendedContext.to_integral(Decimal('2.1')) Decimal("2") @@ -2937,8 +2945,9 @@ other_len = len(str(other.int)) if numdigits > (other_len + prec + 1 - tmp_len): # If the difference in adjusted exps is > prec+1, we know - # other is insignificant, so might as well put a 1 after the precision. - # (since this is only for addition.) Also stops use of massive longs. + # other is insignificant, so might as well put a 1 after the + # precision (since this is only for addition). Also stops + # use of massive longs. extend = prec + 2 - tmp_len if extend <= 0: @@ -2961,13 +2970,13 @@ Used on _WorkRep instances during division. """ adjust = 0 - #If op1 is smaller, make it larger + # If op1 is smaller, make it larger while op2.int > op1.int: op1.int *= 10 op1.exp -= 1 adjust += 1 - #If op2 is too small, make it larger + # If op2 is too small, make it larger while op1.int >= (10 * op2.int): op2.int *= 10 op2.exp -= 1 @@ -2975,7 +2984,7 @@ return op1, op2, adjust -##### Helper Functions ######################################## +##### Helper Functions #################################################### def _convert_other(other): """Convert other to Decimal. @@ -3016,16 +3025,16 @@ if not num: return 0 - #get the sign, get rid of trailing [+-] + # Get the sign, get rid of trailing [+-] sign = 0 if num[0] == '+': num = num[1:] - elif num[0] == '-': #elif avoids '+-nan' + elif num[0] == '-': # elif avoids '+-nan' num = num[1:] sign = 1 if num.startswith('nan'): - if len(num) > 3 and not num[3:].isdigit(): #diagnostic info + if len(num) > 3 and not num[3:].isdigit(): # diagnostic info return 0 return (1, sign, num[3:].lstrip('0')) if num.startswith('snan'): @@ -3035,7 +3044,7 @@ return 0 -##### Setup Specific Contexts ################################ +##### Setup Specific Contexts ############################################ # The default context prototype used by Context() # Is mutable, so that new contexts can have different default values @@ -3068,19 +3077,19 @@ ) -##### Useful Constants (internal use only) #################### +##### Useful Constants (internal use only) ################################ -#Reusable defaults +# Reusable defaults Inf = Decimal('Inf') negInf = Decimal('-Inf') -#Infsign[sign] is infinity w/ that sign +# Infsign[sign] is infinity w/ that sign Infsign = (Inf, negInf) NaN = Decimal('NaN') -##### crud for parsing strings ################################# +##### crud for parsing strings ############################################# import re # There's an optional sign at the start, and an optional exponent @@ -3100,13 +3109,15 @@ ([eE](?P[-+]? \d+))? # \s* $ -""", re.VERBOSE).match #Uncomment the \s* to allow leading or trailing spaces. +""", re.VERBOSE).match # Uncomment the \s* to allow leading or trailing spaces. del re -# return sign, n, p s.t. float string value == -1**sign * n * 10**p exactly - def _string2exact(s): + """Return sign, n, p s.t. + + Float string value == -1**sign * n * 10**p exactly + """ m = _parser(s) if m is None: raise ValueError("invalid literal for Decimal: %r" % s) Modified: python/branches/p3yk/Lib/difflib.py ============================================================================== --- python/branches/p3yk/Lib/difflib.py (original) +++ python/branches/p3yk/Lib/difflib.py Fri Apr 27 21:54:29 2007 @@ -1946,8 +1946,7 @@ fromlist,tolist,flaglist,next_href,next_id = self._convert_flags( fromlist,tolist,flaglist,context,numlines) - import cStringIO - s = cStringIO.StringIO() + s = [] fmt = ' %s%s' + \ '%s%s\n' for i in range(len(flaglist)): @@ -1955,9 +1954,9 @@ # mdiff yields None on separator lines skip the bogus ones # generated for the first line if i > 0: - s.write(' \n \n') + s.append(' \n \n') else: - s.write( fmt % (next_id[i],next_href[i],fromlist[i], + s.append( fmt % (next_id[i],next_href[i],fromlist[i], next_href[i],tolist[i])) if fromdesc or todesc: header_row = '%s%s%s%s' % ( @@ -1969,7 +1968,7 @@ header_row = '' table = self._table_template % dict( - data_rows=s.getvalue(), + data_rows=''.join(s), header_row=header_row, prefix=self._prefix[1]) Modified: python/branches/p3yk/Lib/distutils/__init__.py ============================================================================== --- python/branches/p3yk/Lib/distutils/__init__.py (original) +++ python/branches/p3yk/Lib/distutils/__init__.py Fri Apr 27 21:54:29 2007 @@ -20,4 +20,4 @@ # In general, major and minor version should loosely follow the Python # version number the distutils code was shipped with. # -__version__ = "2.5.0" +__version__ = "2.5.1" Modified: python/branches/p3yk/Lib/distutils/command/build_ext.py ============================================================================== --- python/branches/p3yk/Lib/distutils/command/build_ext.py (original) +++ python/branches/p3yk/Lib/distutils/command/build_ext.py Fri Apr 27 21:54:29 2007 @@ -186,7 +186,7 @@ # for extensions under Cygwin and AtheOS Python's library directory must be # appended to library_dirs if sys.platform[:6] == 'cygwin' or sys.platform[:6] == 'atheos': - if sys.executable.find(sys.exec_prefix) != -1: + if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")): # building third party extensions self.library_dirs.append(os.path.join(sys.prefix, "lib", "python" + get_python_version(), @@ -199,7 +199,7 @@ # Python's library directory must be appended to library_dirs if (sys.platform.startswith('linux') or sys.platform.startswith('gnu')) \ and sysconfig.get_config_var('Py_ENABLE_SHARED'): - if sys.executable.find(sys.exec_prefix) != -1: + if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")): # building third party extensions self.library_dirs.append(sysconfig.get_config_var('LIBDIR')) else: @@ -533,7 +533,8 @@ if self.swig_cpp: log.warn("--swig-cpp is deprecated - use --swig-opts=-c++") - if self.swig_cpp or ('-c++' in self.swig_opts): + if self.swig_cpp or ('-c++' in self.swig_opts) or \ + ('-c++' in extension.swig_opts): target_ext = '.cpp' else: target_ext = '.c' Modified: python/branches/p3yk/Lib/distutils/msvccompiler.py ============================================================================== --- python/branches/p3yk/Lib/distutils/msvccompiler.py (original) +++ python/branches/p3yk/Lib/distutils/msvccompiler.py Fri Apr 27 21:54:29 2007 @@ -187,6 +187,19 @@ j = sys.version.find(")", i) return sys.version[i+len(prefix):j] +def normalize_and_reduce_paths(paths): + """Return a list of normalized paths with duplicates removed. + + The current order of paths is maintained. + """ + # Paths are normalized so things like: /a and /a/ aren't both preserved. + reduced_paths = [] + for p in paths: + np = os.path.normpath(p) + # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. + if np not in reduced_paths: + reduced_paths.append(np) + return reduced_paths class MSVCCompiler (CCompiler) : @@ -270,7 +283,8 @@ self.__paths.append(p) except KeyError: pass - os.environ['path'] = ';'.join(self.__paths) + self.__paths = normalize_and_reduce_paths(self.__paths) + os.environ['path'] = ";".join(self.__paths) self.preprocess_options = None if self.__arch == "Intel": Modified: python/branches/p3yk/Lib/doctest.py ============================================================================== --- python/branches/p3yk/Lib/doctest.py (original) +++ python/branches/p3yk/Lib/doctest.py Fri Apr 27 21:54:29 2007 @@ -2625,8 +2625,23 @@ } def _test(): - r = unittest.TextTestRunner() - r.run(DocTestSuite()) + testfiles = [arg for arg in sys.argv[1:] if arg and arg[0] != '-'] + if testfiles: + for filename in testfiles: + if filename.endswith(".py"): + # It is a module -- insert its dir into sys.path and try to + # import it. If it is part of a package, that possibly won't work + # because of package imports. + dirname, filename = os.path.split(filename) + sys.path.insert(0, dirname) + m = __import__(filename[:-3]) + del sys.path[0] + testmod(m) + else: + testfile(filename, module_relative=False) + else: + r = unittest.TextTestRunner() + r.run(DocTestSuite()) if __name__ == "__main__": _test() Modified: python/branches/p3yk/Lib/email/_parseaddr.py ============================================================================== --- python/branches/p3yk/Lib/email/_parseaddr.py (original) +++ python/branches/p3yk/Lib/email/_parseaddr.py Fri Apr 27 21:54:29 2007 @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2006 Python Software Foundation +# Copyright (C) 2002-2007 Python Software Foundation # Contact: email-sig at python.org """Email address parsing code. @@ -172,6 +172,7 @@ self.pos = 0 self.LWS = ' \t' self.CR = '\r\n' + self.FWS = self.LWS + self.CR self.atomends = self.specials + self.LWS + self.CR # Note that RFC 2822 now specifies `.' as obs-phrase, meaning that it # is obsolete syntax. RFC 2822 requires that we recognize obsolete @@ -418,7 +419,7 @@ plist = [] while self.pos < len(self.field): - if self.field[self.pos] in self.LWS: + if self.field[self.pos] in self.FWS: self.pos += 1 elif self.field[self.pos] == '"': plist.append(self.getquote()) Modified: python/branches/p3yk/Lib/email/header.py ============================================================================== --- python/branches/p3yk/Lib/email/header.py (original) +++ python/branches/p3yk/Lib/email/header.py Fri Apr 27 21:54:29 2007 @@ -39,7 +39,8 @@ \? # literal ? (?P.*?) # non-greedy up to the next ?= is the encoded string \?= # literal ?= - ''', re.VERBOSE | re.IGNORECASE) + (?=[ \t]|$) # whitespace or the end of the string + ''', re.VERBOSE | re.IGNORECASE | re.MULTILINE) # Field name regexp, including trailing colon, but not separating whitespace, # according to RFC 2822. Character range is from tilde to exclamation mark. Modified: python/branches/p3yk/Lib/email/message.py ============================================================================== --- python/branches/p3yk/Lib/email/message.py (original) +++ python/branches/p3yk/Lib/email/message.py Fri Apr 27 21:54:29 2007 @@ -238,7 +238,7 @@ self.del_param('charset') self._charset = None return - if isinstance(charset, str): + if isinstance(charset, basestring): charset = email.charset.Charset(charset) if not isinstance(charset, email.charset.Charset): raise TypeError(charset) @@ -756,7 +756,9 @@ charset = charset[2] # charset character must be in us-ascii range try: - charset = unicode(charset, 'us-ascii').encode('us-ascii') + if isinstance(charset, str): + charset = unicode(charset, 'us-ascii') + charset = charset.encode('us-ascii') except UnicodeError: return failobj # RFC 2046, $4.1.2 says charsets are not case sensitive Modified: python/branches/p3yk/Lib/email/test/test_email.py ============================================================================== --- python/branches/p3yk/Lib/email/test/test_email.py (original) +++ python/branches/p3yk/Lib/email/test/test_email.py Fri Apr 27 21:54:29 2007 @@ -1,4 +1,4 @@ -# Copyright (C) 2001-2006 Python Software Foundation +# Copyright (C) 2001-2007 Python Software Foundation # Contact: email-sig at python.org # email package unit tests @@ -501,6 +501,13 @@ msg.set_payload(x) self.assertEqual(msg.get_payload(decode=True), x) + def test_get_content_charset(self): + msg = Message() + msg.set_charset('us-ascii') + self.assertEqual('us-ascii', msg.get_content_charset()) + msg.set_charset(u'us-ascii') + self.assertEqual('us-ascii', msg.get_content_charset()) + # Test the email.Encoders module @@ -1519,6 +1526,18 @@ hu = make_header(dh).__unicode__() eq(hu, u'The quick brown fox jumped over the lazy dog') + def test_rfc2047_without_whitespace(self): + s = 'Sm=?ISO-8859-1?B?9g==?=rg=?ISO-8859-1?B?5Q==?=sbord' + dh = decode_header(s) + self.assertEqual(dh, [(s, None)]) + + def test_rfc2047_with_whitespace(self): + s = 'Sm =?ISO-8859-1?B?9g==?= rg =?ISO-8859-1?B?5Q==?= sbord' + dh = decode_header(s) + self.assertEqual(dh, [('Sm', None), ('\xf6', 'iso-8859-1'), + ('rg', None), ('\xe5', 'iso-8859-1'), + ('sbord', None)]) + # Test the MIMEMessage class @@ -2164,6 +2183,12 @@ # formataddr() quotes the name if there's a dot in it self.assertEqual(Utils.formataddr((a, b)), y) + def test_multiline_from_comment(self): + x = """\ +Foo +\tBar """ + self.assertEqual(Utils.parseaddr(x), ('Foo Bar', 'foo at example.com')) + def test_quote_dump(self): self.assertEqual( Utils.formataddr(('A Silly; Person', 'person at dom.ain')), Modified: python/branches/p3yk/Lib/email/test/test_email_renamed.py ============================================================================== --- python/branches/p3yk/Lib/email/test/test_email_renamed.py (original) +++ python/branches/p3yk/Lib/email/test/test_email_renamed.py Fri Apr 27 21:54:29 2007 @@ -1,4 +1,4 @@ -# Copyright (C) 2001-2006 Python Software Foundation +# Copyright (C) 2001-2007 Python Software Foundation # Contact: email-sig at python.org # email package unit tests @@ -1524,6 +1524,18 @@ hu = make_header(dh).__unicode__() eq(hu, u'The quick brown fox jumped over the lazy dog') + def test_rfc2047_missing_whitespace(self): + s = 'Sm=?ISO-8859-1?B?9g==?=rg=?ISO-8859-1?B?5Q==?=sbord' + dh = decode_header(s) + self.assertEqual(dh, [(s, None)]) + + def test_rfc2047_with_whitespace(self): + s = 'Sm =?ISO-8859-1?B?9g==?= rg =?ISO-8859-1?B?5Q==?= sbord' + dh = decode_header(s) + self.assertEqual(dh, [('Sm', None), ('\xf6', 'iso-8859-1'), + ('rg', None), ('\xe5', 'iso-8859-1'), + ('sbord', None)]) + # Test the MIMEMessage class @@ -2170,6 +2182,12 @@ # formataddr() quotes the name if there's a dot in it self.assertEqual(utils.formataddr((a, b)), y) + def test_multiline_from_comment(self): + x = """\ +Foo +\tBar """ + self.assertEqual(utils.parseaddr(x), ('Foo Bar', 'foo at example.com')) + def test_quote_dump(self): self.assertEqual( utils.formataddr(('A Silly; Person', 'person at dom.ain')), Modified: python/branches/p3yk/Lib/ftplib.py ============================================================================== --- python/branches/p3yk/Lib/ftplib.py (original) +++ python/branches/p3yk/Lib/ftplib.py Fri Apr 27 21:54:29 2007 @@ -76,9 +76,15 @@ '''An FTP client class. - To create a connection, call the class using these argument: - host, user, passwd, acct - These are all strings, and have default value ''. + To create a connection, call the class using these arguments: + host, user, passwd, acct, timeout + + The first four arguments are all strings, and have default value ''. + timeout must be numeric and defaults to None if not passed, + meaning that no timeout will be set on any ftp socket(s) + If a timeout is passed, then this is now the default timeout for all ftp + socket operations for this instance. + Then use self.connect() with optional host and port argument. To download a file, use ftp.retrlines('RETR ' + filename), @@ -102,33 +108,26 @@ # Initialize host to localhost, port to standard ftp port # Optional arguments are host (for connect()), # and user, passwd, acct (for login()) - def __init__(self, host='', user='', passwd='', acct=''): + def __init__(self, host='', user='', passwd='', acct='', timeout=None): + self.timeout = timeout if host: self.connect(host) - if user: self.login(user, passwd, acct) + if user: + self.login(user, passwd, acct) - def connect(self, host = '', port = 0): + def connect(self, host='', port=0, timeout=None): '''Connect to host. Arguments are: - - host: hostname to connect to (string, default previous host) - - port: port to connect to (integer, default previous port)''' - if host: self.host = host - if port: self.port = port - msg = "getaddrinfo returns an empty list" - for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - self.sock = socket.socket(af, socktype, proto) - self.sock.connect(sa) - except socket.error as err: - msg = err - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg - self.af = af + - host: hostname to connect to (string, default previous host) + - port: port to connect to (integer, default previous port) + ''' + if host != '': + self.host = host + if port > 0: + self.port = port + if timeout is not None: + self.timeout = timeout + self.sock = socket.create_connection((self.host, self.port), self.timeout) + self.af = self.sock.family self.file = self.sock.makefile('rb') self.welcome = self.getresp() return self.welcome Modified: python/branches/p3yk/Lib/genericpath.py ============================================================================== --- python/branches/p3yk/Lib/genericpath.py (original) +++ python/branches/p3yk/Lib/genericpath.py Fri Apr 27 21:54:29 2007 @@ -75,3 +75,32 @@ if s1[i] != s2[i]: return s1[:i] return s1[:n] + +# Split a path in root and extension. +# The extension is everything starting at the last dot in the last +# pathname component; the root is everything before that. +# It is always true that root + ext == p. + +# Generic implementation of splitext, to be parametrized with +# the separators +def _splitext(p, sep, altsep, extsep): + """Split the extension from a pathname. + + Extension is everything from the last dot to the end, ignoring + leading dots. Returns "(root, ext)"; ext may be empty.""" + + sepIndex = p.rfind(sep) + if altsep: + altsepIndex = p.rfind(altsep) + sepIndex = max(sepIndex, altsepIndex) + + dotIndex = p.rfind(extsep) + if dotIndex > sepIndex: + # skip all leading dots + filenameIndex = sepIndex + 1 + while filenameIndex < dotIndex: + if p[filenameIndex] != extsep: + return p[:dotIndex], p[dotIndex:] + filenameIndex += 1 + + return p, '' Modified: python/branches/p3yk/Lib/glob.py ============================================================================== --- python/branches/p3yk/Lib/glob.py (original) +++ python/branches/p3yk/Lib/glob.py Fri Apr 27 21:54:29 2007 @@ -1,8 +1,9 @@ """Filename globbing utility.""" +import sys import os -import fnmatch import re +import fnmatch __all__ = ["glob", "iglob"] @@ -48,13 +49,16 @@ def glob1(dirname, pattern): if not dirname: dirname = os.curdir + if isinstance(pattern, unicode) and not isinstance(dirname, unicode): + dirname = unicode(dirname, sys.getfilesystemencoding() or + sys.getdefaultencoding()) try: names = os.listdir(dirname) except os.error: return [] - if pattern[0]!='.': - names=filter(lambda x: x[0]!='.',names) - return fnmatch.filter(names,pattern) + if pattern[0] != '.': + names = filter(lambda x: x[0] != '.', names) + return fnmatch.filter(names, pattern) def glob0(dirname, basename): if basename == '': Modified: python/branches/p3yk/Lib/heapq.py ============================================================================== --- python/branches/p3yk/Lib/heapq.py (original) +++ python/branches/p3yk/Lib/heapq.py Fri Apr 27 21:54:29 2007 @@ -311,7 +311,7 @@ def merge(*iterables): '''Merge multiple sorted inputs into a single sorted output. - Similar to sorted(itertools.chain(*iterables)) but returns an iterable, + Similar to sorted(itertools.chain(*iterables)) but returns a generator, does not pull the data into memory all at once, and assumes that each of the input streams is already sorted (smallest to largest). Modified: python/branches/p3yk/Lib/httplib.py ============================================================================== --- python/branches/p3yk/Lib/httplib.py (original) +++ python/branches/p3yk/Lib/httplib.py Fri Apr 27 21:54:29 2007 @@ -625,7 +625,8 @@ debuglevel = 0 strict = 0 - def __init__(self, host, port=None, strict=None): + def __init__(self, host, port=None, strict=None, timeout=None): + self.timeout = timeout self.sock = None self._buffer = [] self.__response = None @@ -658,25 +659,8 @@ def connect(self): """Connect to the host and port specified in __init__.""" - msg = "getaddrinfo returns an empty list" - for res in socket.getaddrinfo(self.host, self.port, 0, - socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - self.sock = socket.socket(af, socktype, proto) - if self.debuglevel > 0: - print("connect: (%s, %s)" % (self.host, self.port)) - self.sock.connect(sa) - except socket.error as msg: - if self.debuglevel > 0: - print('connect fail:', (self.host, self.port)) - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg + self.sock = socket.create_connection((self.host,self.port), + self.timeout) def close(self): """Close the connection to the HTTP server.""" @@ -948,8 +932,8 @@ self.__state = _CS_IDLE if response.will_close: - # Pass the socket to the response - self.sock = None + # this effectively passes the connection to the response + self.close() else: # remember this, so we can tell when it is complete self.__response = response Modified: python/branches/p3yk/Lib/idlelib/MultiCall.py ============================================================================== --- python/branches/p3yk/Lib/idlelib/MultiCall.py (original) +++ python/branches/p3yk/Lib/idlelib/MultiCall.py Fri Apr 27 21:54:29 2007 @@ -350,6 +350,8 @@ triplets.append(triplet) def event_delete(self, virtual, *sequences): + if virtual not in self.__eventinfo: + return func, triplets = self.__eventinfo[virtual] for seq in sequences: triplet = _parse_sequence(seq) Modified: python/branches/p3yk/Lib/imaplib.py ============================================================================== --- python/branches/p3yk/Lib/imaplib.py (original) +++ python/branches/p3yk/Lib/imaplib.py Fri Apr 27 21:54:29 2007 @@ -746,8 +746,10 @@ if not command in Commands: raise self.error("Unknown IMAP4 UID command: %s" % command) if self.state not in Commands[command]: - raise self.error('command %s illegal in state %s' - % (command, self.state)) + raise self.error("command %s illegal in state %s, " + "only allowed in states %s" % + (command, self.state, + ', '.join(Commands[command]))) name = 'UID' typ, dat = self._simple_command(name, command, *args) if command in ('SEARCH', 'SORT'): @@ -811,8 +813,10 @@ if self.state not in Commands[name]: self.literal = None - raise self.error( - 'command %s illegal in state %s' % (name, self.state)) + raise self.error("command %s illegal in state %s, " + "only allowed in states %s" % + (name, self.state, + ', '.join(Commands[name]))) for typ in ('OK', 'NO', 'BAD'): if typ in self.untagged_responses: Modified: python/branches/p3yk/Lib/logging/handlers.py ============================================================================== --- python/branches/p3yk/Lib/logging/handlers.py (original) +++ python/branches/p3yk/Lib/logging/handlers.py Fri Apr 27 21:54:29 2007 @@ -365,12 +365,14 @@ self.retryMax = 30.0 self.retryFactor = 2.0 - def makeSocket(self): + def makeSocket(self, timeout=1): """ A factory method which allows subclasses to define the precise type of socket they want. """ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if hasattr(s, 'settimeout'): + s.settimeout(timeout) s.connect((self.host, self.port)) return s Modified: python/branches/p3yk/Lib/macpath.py ============================================================================== --- python/branches/p3yk/Lib/macpath.py (original) +++ python/branches/p3yk/Lib/macpath.py Fri Apr 27 21:54:29 2007 @@ -2,6 +2,7 @@ import os from stat import * +import genericpath from genericpath import * __all__ = ["normcase","isabs","join","splitdrive","split","splitext", @@ -69,17 +70,8 @@ def splitext(p): - """Split a path into root and extension. - The extension is everything starting at the last dot in the last - pathname component; the root is everything before that. - It is always true that root + ext == p.""" - - i = p.rfind('.') - if i<=p.rfind(':'): - return p, '' - else: - return p[:i], p[i:] - + return genericpath._splitext(p, sep, altsep, extsep) +splitext.__doc__ = genericpath._splitext.__doc__ def splitdrive(p): """Split a pathname into a drive specification and the rest of the Modified: python/branches/p3yk/Lib/ntpath.py ============================================================================== --- python/branches/p3yk/Lib/ntpath.py (original) +++ python/branches/p3yk/Lib/ntpath.py Fri Apr 27 21:54:29 2007 @@ -8,6 +8,7 @@ import os import stat import sys +import genericpath from genericpath import * __all__ = ["normcase","isabs","join","splitdrive","split","splitext", @@ -15,7 +16,7 @@ "getatime","getctime", "islink","exists","lexists","isdir","isfile", "ismount","walk","expanduser","expandvars","normpath","abspath", "splitunc","curdir","pardir","sep","pathsep","defpath","altsep", - "extsep","devnull","realpath","supports_unicode_filenames"] + "extsep","devnull","realpath","supports_unicode_filenames","relpath"] # strings representing various path-related bits and pieces curdir = '.' @@ -182,16 +183,8 @@ # It is always true that root + ext == p. def splitext(p): - """Split the extension from a pathname. - - Extension is everything from the last dot to the end. - Return (root, ext), either part may be empty.""" - - i = p.rfind('.') - if i<=max(p.rfind('/'), p.rfind('\\')): - return p, '' - else: - return p[:i], p[i:] + return genericpath._splitext(p, sep, altsep, extsep) +splitext.__doc__ = genericpath._splitext.__doc__ # Return the tail (basename) part of a path. @@ -285,36 +278,44 @@ i, n = 1, len(path) while i < n and path[i] not in '/\\': i = i + 1 - if i == 1: - if 'HOME' in os.environ: - userhome = os.environ['HOME'] - elif not 'HOMEPATH' in os.environ: - return path - else: - try: - drive = os.environ['HOMEDRIVE'] - except KeyError: - drive = '' - userhome = join(drive, os.environ['HOMEPATH']) - else: + + if 'HOME' in os.environ: + userhome = os.environ['HOME'] + elif 'USERPROFILE' in os.environ: + userhome = os.environ['USERPROFILE'] + elif not 'HOMEPATH' in os.environ: return path + else: + try: + drive = os.environ['HOMEDRIVE'] + except KeyError: + drive = '' + userhome = join(drive, os.environ['HOMEPATH']) + + if i != 1: #~user + userhome = join(dirname(userhome), path[1:i]) + return userhome + path[i:] # Expand paths containing shell variable substitutions. # The following rules apply: # - no expansion within single quotes -# - no escape character, except for '$$' which is translated into '$' +# - '$$' is translated into '$' +# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2% # - ${varname} is accepted. -# - varnames can be made out of letters, digits and the character '_' +# - $varname is accepted. +# - %varname% is accepted. +# - varnames can be made out of letters, digits and the characters '_-' +# (though is not verifed in the ${varname} and %varname% cases) # XXX With COMMAND.COM you can use any characters in a variable name, # XXX except '^|<>='. def expandvars(path): - """Expand shell variables of form $var and ${var}. + """Expand shell variables of the forms $var, ${var} and %var%. Unknown variables are left unchanged.""" - if '$' not in path: + if '$' not in path and '%' not in path: return path import string varchars = string.ascii_letters + string.digits + '_-' @@ -332,6 +333,24 @@ except ValueError: res = res + path index = pathlen - 1 + elif c == '%': # variable or '%' + if path[index + 1:index + 2] == '%': + res = res + c + index = index + 1 + else: + path = path[index+1:] + pathlen = len(path) + try: + index = path.index('%') + except ValueError: + res = res + '%' + path + index = pathlen - 1 + else: + var = path[:index] + if var in os.environ: + res = res + os.environ[var] + else: + res = res + '%' + var + '%' elif c == '$': # variable or '$$' if path[index + 1:index + 2] == '$': res = res + c @@ -446,3 +465,29 @@ # Win9x family and earlier have no Unicode filename support. supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and sys.getwindowsversion()[3] >= 2) + +def relpath(path, start=curdir): + """Return a relative version of a path""" + + if not path: + raise ValueError("no path specified") + start_list = abspath(start).split(sep) + path_list = abspath(path).split(sep) + if start_list[0].lower() != path_list[0].lower(): + unc_path, rest = splitunc(path) + unc_start, rest = splitunc(start) + if bool(unc_path) ^ bool(unc_start): + raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" + % (path, start)) + else: + raise ValueError("path is on drive %s, start on drive %s" + % (path_list[0], start_list[0])) + # Work out how much of the filepath is shared by start and path. + for i in range(min(len(start_list), len(path_list))): + if start_list[i].lower() != path_list[i].lower(): + break + else: + i += 1 + + rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + return join(*rel_list) Modified: python/branches/p3yk/Lib/os.py ============================================================================== --- python/branches/p3yk/Lib/os.py (original) +++ python/branches/p3yk/Lib/os.py Fri Apr 27 21:54:29 2007 @@ -221,7 +221,7 @@ __all__.extend(["makedirs", "removedirs", "renames"]) -def walk(top, topdown=True, onerror=None): +def walk(top, topdown=True, onerror=None, followlinks=False): """Directory tree generator. For each directory in the directory tree rooted at top (including top @@ -257,6 +257,10 @@ to abort the walk. Note that the filename is available as the filename attribute of the exception object. + By default, os.walk does not follow symbolic links to subdirectories on + systems that support them. In order to get this functionality, set the + optional argument 'followlinks' to true. + Caution: if you pass a relative pathname for top, don't change the current working directory between resumptions of walk. walk never changes the current directory, and assumes that the client doesn't @@ -300,8 +304,8 @@ yield top, dirs, nondirs for name in dirs: path = join(top, name) - if not islink(path): - for x in walk(path, topdown, onerror): + if followlinks or not islink(path): + for x in walk(path, topdown, onerror, followlinks): yield x if not topdown: yield top, dirs, nondirs Modified: python/branches/p3yk/Lib/pdb.doc ============================================================================== --- python/branches/p3yk/Lib/pdb.doc (original) +++ python/branches/p3yk/Lib/pdb.doc Fri Apr 27 21:54:29 2007 @@ -131,6 +131,12 @@ r(eturn) Continue execution until the current function returns. +run [args...] + Restart the debugged python program. If a string is supplied it is + splitted with "shlex", and the result is used as the new sys.argv. + History, breakpoints, actions and debugger options are preserved. + "restart" is an alias for "run". + c(ont(inue)) Continue execution, only stop when a breakpoint is encountered. Modified: python/branches/p3yk/Lib/pdb.py ============================================================================== --- python/branches/p3yk/Lib/pdb.py (original) +++ python/branches/p3yk/Lib/pdb.py Fri Apr 27 21:54:29 2007 @@ -13,6 +13,12 @@ import re import pprint import traceback + + +class Restart(Exception): + """Causes a debugger to be restarted for the debugged python program.""" + pass + # Create a custom safe Repr instance and increase its maxstring. # The default of 30 truncates error messages too easily. _repr = Repr() @@ -484,11 +490,16 @@ except ValueError: # something went wrong print('Breakpoint index %r is not a number' % args[0], file=self.stdout) + return try: cond = args[1] except: cond = None - bp = bdb.Breakpoint.bpbynumber[bpnum] + try: + bp = bdb.Breakpoint.bpbynumber[bpnum] + except IndexError: + print >>self.stdout, 'Breakpoint index %r is not valid' % args[0] + return if bp: bp.cond = cond if not cond: @@ -503,11 +514,16 @@ except ValueError: # something went wrong print('Breakpoint index %r is not a number' % args[0], file=self.stdout) + return try: count = int(args[1].strip()) except: count = 0 - bp = bdb.Breakpoint.bpbynumber[bpnum] + try: + bp = bdb.Breakpoint.bpbynumber[bpnum] + except IndexError: + print >>self.stdout, 'Breakpoint index %r is not valid' % args[0] + return if bp: bp.ignore = count if count > 0: @@ -601,6 +617,18 @@ return 1 do_n = do_next + def do_run(self, arg): + """Restart program by raising an exception to be caught in the main debugger + loop. If arguments were given, set them in sys.argv.""" + if arg: + import shlex + argv0 = sys.argv[0:1] + sys.argv = shlex.split(arg) + sys.argv[:0] = argv0 + raise Restart + + do_restart = do_run + def do_return(self, arg): self.set_return(self.curframe) return 1 @@ -1005,6 +1033,15 @@ (Pdb) global list_options; list_options = ['-l'] (Pdb)""", file=self.stdout) + def help_run(self): + print("""run [args...] +Restart the debugged python program. If a string is supplied, it is +splitted with "shlex" and the result is used as the new sys.argv. +History, breakpoints, actions and debugger options are preserved. +"restart" is an alias for "run".""") + + help_restart = help_run + def help_quit(self): self.help_q() @@ -1113,11 +1150,17 @@ return None def _runscript(self, filename): - # Start with fresh empty copy of globals and locals and tell the script - # that it's being run as __main__ to avoid scripts being able to access - # the pdb.py namespace. - globals_ = {"__name__" : "__main__"} - locals_ = globals_ + # The script has to run in __main__ namespace (or imports from + # __main__ will break). + # + # So we clear up the __main__ and set several special variables + # (this gets rid of pdb's globals and cleans old variables on restarts). + import __main__ + __main__.__dict__.clear() + __main__.__dict__.update({"__name__" : "__main__", + "__file__" : filename, + "__builtins__": __builtins__, + }) # When bdb sets tracing, a number of call and line events happens # BEFORE debugger even reaches user's code (and the exact sequence of @@ -1128,7 +1171,7 @@ self.mainpyfile = self.canonic(filename) self._user_requested_quit = 0 statement = 'execfile( "%s")' % filename - self.run(statement, globals=globals_, locals=locals_) + self.run(statement) # Simplified interface @@ -1197,9 +1240,8 @@ # Note on saving/restoring sys.argv: it's a good idea when sys.argv was # modified by the script being debugged. It's a bad idea when it was - # changed by the user from the command line. The best approach would be to - # have a "restart" command which would allow explicit specification of - # command line arguments. + # changed by the user from the command line. There is a "restart" command which + # allows explicit specification of command line arguments. pdb = Pdb() while 1: try: @@ -1207,6 +1249,9 @@ if pdb._user_requested_quit: break print("The program finished and will be restarted") + except Restart: + print("Restarting", mainpyfile, "with arguments:") + print("\t" + " ".join(sys.argv[1:])) except SystemExit: # In most cases SystemExit does not warrant a post-mortem session. print("The program exited via sys.exit(). Exit status: ", end=' ') @@ -1223,5 +1268,6 @@ # When invoked as main program, invoke the debugger on a script -if __name__=='__main__': - main() +if __name__ == '__main__': + import pdb + pdb.main() Modified: python/branches/p3yk/Lib/popen2.py ============================================================================== --- python/branches/p3yk/Lib/popen2.py (original) +++ python/branches/p3yk/Lib/popen2.py Fri Apr 27 21:54:29 2007 @@ -200,45 +200,3 @@ return inst.fromchild, inst.tochild __all__.extend(["Popen3", "Popen4"]) - -def _test(): - # When the test runs, there shouldn't be any open pipes - _cleanup() - assert not _active, "Active pipes when test starts " + repr([c.cmd for c in _active]) - cmd = "cat" - teststr = "ab cd\n" - if os.name == "nt": - cmd = "more" - # "more" doesn't act the same way across Windows flavors, - # sometimes adding an extra newline at the start or the - # end. So we strip whitespace off both ends for comparison. - expected = teststr.strip() - print("testing popen2...") - r, w = popen2(cmd) - w.write(teststr) - w.close() - got = r.read() - if got.strip() != expected: - raise ValueError("wrote %r read %r" % (teststr, got)) - print("testing popen3...") - try: - r, w, e = popen3([cmd]) - except: - r, w, e = popen3(cmd) - w.write(teststr) - w.close() - got = r.read() - if got.strip() != expected: - raise ValueError("wrote %r read %r" % (teststr, got)) - got = e.read() - if got: - raise ValueError("unexpected %r on stderr" % (got,)) - for inst in _active[:]: - inst.wait() - _cleanup() - if _active: - raise ValueError("_active not empty") - print("All OK") - -if __name__ == '__main__': - _test() Modified: python/branches/p3yk/Lib/poplib.py ============================================================================== --- python/branches/p3yk/Lib/poplib.py (original) +++ python/branches/p3yk/Lib/poplib.py Fri Apr 27 21:54:29 2007 @@ -76,24 +76,10 @@ """ - def __init__(self, host, port = POP3_PORT): + def __init__(self, host, port=POP3_PORT, timeout=None): self.host = host self.port = port - msg = "getaddrinfo returns an empty list" - self.sock = None - for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - self.sock = socket.socket(af, socktype, proto) - self.sock.connect(sa) - except socket.error as msg: - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg + self.sock = socket.create_connection((host, port), timeout) self.file = self.sock.makefile('rb') self._debugging = 0 self.welcome = self._getresp() Modified: python/branches/p3yk/Lib/posixpath.py ============================================================================== --- python/branches/p3yk/Lib/posixpath.py (original) +++ python/branches/p3yk/Lib/posixpath.py Fri Apr 27 21:54:29 2007 @@ -12,6 +12,7 @@ import os import stat +import genericpath from genericpath import * __all__ = ["normcase","isabs","join","splitdrive","split","splitext", @@ -20,7 +21,7 @@ "ismount","walk","expanduser","expandvars","normpath","abspath", "samefile","sameopenfile","samestat", "curdir","pardir","sep","pathsep","defpath","altsep","extsep", - "devnull","realpath","supports_unicode_filenames"] + "devnull","realpath","supports_unicode_filenames","relpath"] # strings representing various path-related bits and pieces curdir = '.' @@ -88,14 +89,8 @@ # It is always true that root + ext == p. def splitext(p): - """Split the extension from a pathname. Extension is everything from the - last dot to the end. Returns "(root, ext)", either part may be empty.""" - i = p.rfind('.') - if i<=p.rfind('/'): - return p, '' - else: - return p[:i], p[i:] - + return genericpath._splitext(p, sep, altsep, extsep) +splitext.__doc__ = genericpath._splitext.__doc__ # Split a pathname into a drive specification and the rest of the # path. Useful on DOS/Windows/NT; on Unix, the drive is always empty. @@ -387,3 +382,18 @@ return path supports_unicode_filenames = False + +def relpath(path, start=curdir): + """Return a relative version of a path""" + + if not path: + raise ValueError("no path specified") + + start_list = abspath(start).split(sep) + path_list = abspath(path).split(sep) + + # Work out how much of the filepath is shared by start and path. + i = len(commonprefix([start_list, path_list])) + + rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + return join(*rel_list) Modified: python/branches/p3yk/Lib/pydoc.py ============================================================================== --- python/branches/p3yk/Lib/pydoc.py (original) +++ python/branches/p3yk/Lib/pydoc.py Fri Apr 27 21:54:29 2007 @@ -854,7 +854,7 @@ if imclass is not cl: note = ' from ' + self.classlink(imclass, mod) else: - if object.im_self: + if object.im_self is not None: note = ' method of %s instance' % self.classlink( object.im_self.__class__, mod) else: @@ -1232,7 +1232,7 @@ if imclass is not cl: note = ' from ' + classname(imclass, mod) else: - if object.im_self: + if object.im_self is not None: note = ' method of %s instance' % classname( object.im_self.__class__, mod) else: @@ -1468,6 +1468,27 @@ else: return thing, getattr(thing, '__name__', None) +def render_doc(thing, title='Python Library Documentation: %s', forceload=0): + """Render text documentation, given an object or a path to an object.""" + object, name = resolve(thing, forceload) + desc = describe(object) + module = inspect.getmodule(object) + if name and '.' in name: + desc += ' in ' + name[:name.rfind('.')] + elif module and module is not object: + desc += ' in module ' + module.__name__ + elif not (inspect.ismodule(object) or + inspect.isclass(object) or + inspect.isroutine(object) or + inspect.isgetsetdescriptor(object) or + inspect.ismemberdescriptor(object) or + isinstance(object, property)): + # If the passed object is a piece of data or an instance, + # document its available methods instead of its value. + object = type(object) + desc += ' object' + return title % desc + '\n\n' + text.document(object, name) + def doc(thing, title='Python Library Documentation: %s', forceload=0): """Display text documentation, given an object or a path to an object.""" try: @@ -1488,7 +1509,7 @@ # document its available methods instead of its value. object = type(object) desc += ' object' - pager(title % desc + '\n\n' + text.document(object, name)) + pager(render_doc(thing, title, forceload)) except (ImportError, ErrorDuringImport) as value: print(value) @@ -1519,6 +1540,7 @@ class Helper: keywords = { 'and': 'BOOLEAN', + 'as': 'with', 'assert': ('ref/assert', ''), 'break': ('ref/break', 'while for'), 'class': ('ref/class', 'CLASSES SPECIALMETHODS'), @@ -1546,6 +1568,7 @@ 'return': ('ref/return', 'FUNCTIONS'), 'try': ('ref/try', 'EXCEPTIONS'), 'while': ('ref/while', 'break continue if TRUTHVALUE'), + 'with': ('ref/with', 'CONTEXTMANAGERS EXCEPTIONS yield'), 'yield': ('ref/yield', ''), } @@ -1626,6 +1649,7 @@ 'LOOPING': ('ref/compound', 'for while break continue'), 'TRUTHVALUE': ('lib/truth', 'if while and or not BASICMETHODS'), 'DEBUGGING': ('lib/module-pdb', 'pdb'), + 'CONTEXTMANAGERS': ('ref/context-managers', 'with'), } def __init__(self, input, output): @@ -1634,16 +1658,21 @@ self.docdir = None execdir = os.path.dirname(sys.executable) homedir = os.environ.get('PYTHONHOME') + join = os.path.join for dir in [os.environ.get('PYTHONDOCS'), homedir and os.path.join(homedir, 'doc'), - os.path.join(execdir, 'doc'), - '/usr/doc/python-docs-' + sys.version.split()[0], - '/usr/doc/python-' + sys.version.split()[0], - '/usr/doc/python-docs-' + sys.version[:3], - '/usr/doc/python-' + sys.version[:3], - os.path.join(sys.prefix, 'Resources/English.lproj/Documentation')]: - if dir and os.path.isdir(os.path.join(dir, 'lib')): + join(execdir, 'doc'), # for Windows + join(sys.prefix, 'doc/python-docs-' + sys.version.split()[0]), + join(sys.prefix, 'doc/python-' + sys.version.split()[0]), + join(sys.prefix, 'doc/python-docs-' + sys.version[:3]), + join(sys.prefix, 'doc/python-' + sys.version[:3]), + join(sys.prefix, 'Resources/English.lproj/Documentation')]: + if dir and os.path.isdir(join(dir, 'lib')): self.docdir = dir + break + if dir and os.path.isdir(join(dir, 'html', 'lib')): + self.docdir = join(dir, 'html') + break def __repr__(self): if inspect.stack()[1][3] == '?': Modified: python/branches/p3yk/Lib/rexec.py ============================================================================== --- python/branches/p3yk/Lib/rexec.py (original) +++ python/branches/p3yk/Lib/rexec.py Fri Apr 27 21:54:29 2007 @@ -29,7 +29,7 @@ class FileBase: ok_file_methods = ('fileno', 'flush', 'isatty', 'read', 'readline', - 'readlines', 'seek', 'tell', 'write', 'writelines', + 'readlines', 'seek', 'tell', 'write', 'writelines', '__iter__') @@ -181,7 +181,7 @@ """ - raise RuntimeError, "This code is not secure in Python 2.2 and 2.3" + raise RuntimeError, "This code is not secure in Python 2.2 and later" ihooks._Verbose.__init__(self, verbose) # XXX There's a circular reference here: Modified: python/branches/p3yk/Lib/robotparser.py ============================================================================== --- python/branches/p3yk/Lib/robotparser.py (original) +++ python/branches/p3yk/Lib/robotparser.py Fri Apr 27 21:54:29 2007 @@ -65,7 +65,7 @@ lines.append(line.strip()) line = f.readline() self.errcode = opener.errcode - if self.errcode == 401 or self.errcode == 403: + if self.errcode in (401, 403): self.disallow_all = True _debug("disallow all") elif self.errcode >= 400: @@ -168,10 +168,7 @@ def __str__(self): - ret = "" - for entry in self.entries: - ret = ret + str(entry) + "\n" - return ret + return ''.join([str(entry) + "\n" for entry in self.entries]) class RuleLine: @@ -198,12 +195,12 @@ self.rulelines = [] def __str__(self): - ret = "" + ret = [] for agent in self.useragents: - ret = ret + "User-agent: "+agent+"\n" + ret.extend(["User-agent: ", agent, "\n"]) for line in self.rulelines: - ret = ret + str(line) + "\n" - return ret + ret.extend([str(line), "\n"]) + return ''.join(ret) def applies_to(self, useragent): """check if this entry applies to the specified agent""" Modified: python/branches/p3yk/Lib/sched.py ============================================================================== --- python/branches/p3yk/Lib/sched.py (original) +++ python/branches/p3yk/Lib/sched.py Fri Apr 27 21:54:29 2007 @@ -72,7 +72,7 @@ def empty(self): """Check whether the queue is empty.""" - return not not self.queue + return not self.queue def run(self): """Execute events until the queue is empty. Modified: python/branches/p3yk/Lib/site.py ============================================================================== --- python/branches/p3yk/Lib/site.py (original) +++ python/branches/p3yk/Lib/site.py Fri Apr 27 21:54:29 2007 @@ -134,7 +134,7 @@ for line in f: if line.startswith("#"): continue - if line.startswith("import"): + if line.startswith("import ") or line.startswith("import\t"): exec(line) continue line = line.rstrip() Modified: python/branches/p3yk/Lib/smtplib.py ============================================================================== --- python/branches/p3yk/Lib/smtplib.py (original) +++ python/branches/p3yk/Lib/smtplib.py Fri Apr 27 21:54:29 2007 @@ -226,10 +226,11 @@ debuglevel = 0 file = None helo_resp = None + ehlo_msg = "ehlo" ehlo_resp = None does_esmtp = 0 - def __init__(self, host = '', port = 0, local_hostname = None): + def __init__(self, host='', port=0, local_hostname=None, timeout=None): """Initialize a new instance. If specified, `host' is the name of the remote host to which to @@ -240,6 +241,7 @@ the local hostname is found using socket.getfqdn(). """ + self.timeout = timeout self.esmtp_features = {} self.default_port = SMTP_PORT if host: @@ -273,12 +275,11 @@ """ self.debuglevel = debuglevel - def _get_socket(self,af, socktype, proto,sa): + def _get_socket(self, port, host, timeout): # This makes it simpler for SMTP_SSL to use the SMTP connect code # and just alter the socket connection bit. - self.sock = socket.socket(af, socktype, proto) if self.debuglevel > 0: print('connect:', (host, port), file=stderr) - self.sock.connect(sa) + return socket.create_connection((port, host), timeout) def connect(self, host='localhost', port = 0): """Connect to a host on a given port. @@ -297,24 +298,10 @@ host, port = host[:i], host[i+1:] try: port = int(port) except ValueError: - raise socket.error, "nonnumeric port" + raise socket.error("nonnumeric port") if not port: port = self.default_port if self.debuglevel > 0: print('connect:', (host, port), file=stderr) - msg = "getaddrinfo returns an empty list" - self.sock = None - for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - self._get_socket(af,socktype,proto,sa) - except socket.error as msg: - if self.debuglevel > 0: print('connect fail:', msg, file=stderr) - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg + self.sock = self._get_socket(host, port, self.timeout) (code, msg) = self.getreply() if self.debuglevel > 0: print("connect:", msg, file=stderr) return (code, msg) @@ -401,7 +388,7 @@ host. """ self.esmtp_features = {} - self.putcmd("ehlo", name or self.local_hostname) + self.putcmd(self.ehlo_msg, name or self.local_hostname) (code,msg)=self.getreply() # According to RFC1869 some (badly written) # MTA's will disconnect on an ehlo. Toss an exception if @@ -731,21 +718,64 @@ are also optional - they can contain a PEM formatted private key and certificate chain file for the SSL connection. """ - def __init__(self, host = '', port = 0, local_hostname = None, - keyfile = None, certfile = None): + def __init__(self, host='', port=0, local_hostname=None, + keyfile=None, certfile=None, timeout=None): self.keyfile = keyfile self.certfile = certfile - SMTP.__init__(self,host,port,local_hostname) + SMTP.__init__(self, host, port, local_hostname, timeout) self.default_port = SMTP_SSL_PORT - def _get_socket(self,af, socktype, proto,sa): - self.sock = socket.socket(af, socktype, proto) + def _get_socket(self, host, port, timeout): if self.debuglevel > 0: print('connect:', (host, port), file=stderr) - self.sock.connect(sa) + self.sock = socket.create_connection((host, port), timeout) sslobj = socket.ssl(self.sock, self.keyfile, self.certfile) self.sock = SSLFakeSocket(self.sock, sslobj) self.file = SSLFakeFile(sslobj) +# +# LMTP extension +# +LMTP_PORT = 2003 + +class LMTP(SMTP): + """LMTP - Local Mail Transfer Protocol + + The LMTP protocol, which is very similar to ESMTP, is heavily based + on the standard SMTP client. It's common to use Unix sockets for LMTP, + so our connect() method must support that as well as a regular + host:port server. To specify a Unix socket, you must use an absolute + path as the host, starting with a '/'. + + Authentication is supported, using the regular SMTP mechanism. When + using a Unix socket, LMTP generally don't support or require any + authentication, but your mileage might vary.""" + + ehlo_msg = "lhlo" + + def __init__(self, host = '', port = LMTP_PORT, local_hostname = None): + """Initialize a new instance.""" + SMTP.__init__(self, host, port, local_hostname) + + def connect(self, host = 'localhost', port = 0): + """Connect to the LMTP daemon, on either a Unix or a TCP socket.""" + if host[0] != '/': + return SMTP.connect(self, host, port) + + # Handle Unix-domain sockets. + try: + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.sock.connect(host) + except socket.error as msg: + if self.debuglevel > 0: print>>stderr, 'connect fail:', host + if self.sock: + self.sock.close() + self.sock = None + raise socket.error(msg) + (code, msg) = self.getreply() + if self.debuglevel > 0: print>>stderr, "connect:", msg + return (code, msg) + + # Test the sendmail method, which tests most of the others. # Note: This always sends to localhost. if __name__ == '__main__': Modified: python/branches/p3yk/Lib/socket.py ============================================================================== --- python/branches/p3yk/Lib/socket.py (original) +++ python/branches/p3yk/Lib/socket.py Fri Apr 27 21:54:29 2007 @@ -24,6 +24,7 @@ ssl() -- secure socket layer support (only available if configured) socket.getdefaulttimeout() -- get the default timeout value socket.setdefaulttimeout() -- set the default timeout value +create_connection() -- connects to an address, with an optional timeout [*] not available on all platforms! @@ -139,8 +140,6 @@ __slots__ = [] def _dummy(*args): raise error(EBADF, 'Bad file descriptor') - def close(self): - pass # All _delegate_methods must also be initialized here. send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy __getattr__ = _dummy @@ -159,7 +158,6 @@ setattr(self, method, getattr(_sock, method)) def close(self): - self._sock.close() self._sock = _closedsocket() dummy = self._sock._dummy for method in _delegate_methods: @@ -414,3 +412,32 @@ if not line: raise StopIteration return line + + +def create_connection(address, timeout=None): + """Connect to address (host, port) with an optional timeout. + + Provides access to socketobject timeout for higher-level + protocols. Passing a timeout will set the timeout on the + socket instance (if not present, or passed as None, the + default global timeout setting will be used). + """ + + msg = "getaddrinfo returns an empty list" + host, port = address + for res in getaddrinfo(host, port, 0, SOCK_STREAM): + af, socktype, proto, canonname, sa = res + sock = None + try: + sock = socket(af, socktype, proto) + if timeout is not None: + sock.settimeout(timeout) + sock.connect(sa) + return sock + + except error as err: + msg = err + if sock is not None: + sock.close() + + raise error(msg) Modified: python/branches/p3yk/Lib/sre.py ============================================================================== --- python/branches/p3yk/Lib/sre.py (original) +++ python/branches/p3yk/Lib/sre.py Fri Apr 27 21:54:29 2007 @@ -8,3 +8,6 @@ from re import * from re import __all__ + +# old pickles expect the _compile() reconstructor in this module +from re import _compile Modified: python/branches/p3yk/Lib/subprocess.py ============================================================================== --- python/branches/p3yk/Lib/subprocess.py (original) +++ python/branches/p3yk/Lib/subprocess.py Fri Apr 27 21:54:29 2007 @@ -597,7 +597,7 @@ # either have to redirect all three or none. If the subprocess # user has only redirected one or two handles, we are # automatically creating PIPEs for the rest. We should close - # these after the process is started. See bug #1124861. + # these after the process is started. See bug #1124861. if mswindows: if stdin is None and p2cwrite is not None: os.close(p2cwrite) @@ -629,7 +629,7 @@ return data - def __del__(self): + def __del__(self, sys=sys): if not self._child_created: # We didn't get to successfully create a child process. return Modified: python/branches/p3yk/Lib/tarfile.py ============================================================================== --- python/branches/p3yk/Lib/tarfile.py (original) +++ python/branches/p3yk/Lib/tarfile.py Fri Apr 27 21:54:29 2007 @@ -33,7 +33,7 @@ __version__ = "$Revision$" # $Source$ -version = "0.8.0" +version = "0.9.0" __author__ = "Lars Gust?bel (lars at gustaebel.de)" __date__ = "$Date$" __cvsid__ = "$Id$" @@ -50,6 +50,7 @@ import time import struct import copy +import re if sys.platform == 'mac': # This module needs work for MacOS9, especially in the area of pathname @@ -71,42 +72,60 @@ #--------------------------------------------------------- # tar constants #--------------------------------------------------------- -NUL = "\0" # the null character -BLOCKSIZE = 512 # length of processing blocks +NUL = "\0" # the null character +BLOCKSIZE = 512 # length of processing blocks RECORDSIZE = BLOCKSIZE * 20 # length of records -MAGIC = "ustar" # magic tar string -VERSION = "00" # version number +GNU_MAGIC = "ustar \0" # magic gnu tar string +POSIX_MAGIC = "ustar\x0000" # magic posix tar string -LENGTH_NAME = 100 # maximum length of a filename -LENGTH_LINK = 100 # maximum length of a linkname -LENGTH_PREFIX = 155 # maximum length of the prefix field -MAXSIZE_MEMBER = 077777777777 # maximum size of a file (11 octal digits) +LENGTH_NAME = 100 # maximum length of a filename +LENGTH_LINK = 100 # maximum length of a linkname +LENGTH_PREFIX = 155 # maximum length of the prefix field -REGTYPE = "0" # regular file +REGTYPE = "0" # regular file AREGTYPE = "\0" # regular file -LNKTYPE = "1" # link (inside tarfile) -SYMTYPE = "2" # symbolic link -CHRTYPE = "3" # character special device -BLKTYPE = "4" # block special device -DIRTYPE = "5" # directory +LNKTYPE = "1" # link (inside tarfile) +SYMTYPE = "2" # symbolic link +CHRTYPE = "3" # character special device +BLKTYPE = "4" # block special device +DIRTYPE = "5" # directory FIFOTYPE = "6" # fifo special device CONTTYPE = "7" # contiguous file -GNUTYPE_LONGNAME = "L" # GNU tar extension for longnames -GNUTYPE_LONGLINK = "K" # GNU tar extension for longlink -GNUTYPE_SPARSE = "S" # GNU tar extension for sparse file +GNUTYPE_LONGNAME = "L" # GNU tar longname +GNUTYPE_LONGLINK = "K" # GNU tar longlink +GNUTYPE_SPARSE = "S" # GNU tar sparse file + +XHDTYPE = "x" # POSIX.1-2001 extended header +XGLTYPE = "g" # POSIX.1-2001 global header +SOLARIS_XHDTYPE = "X" # Solaris extended header + +USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format +GNU_FORMAT = 1 # GNU tar format +PAX_FORMAT = 2 # POSIX.1-2001 (pax) format +DEFAULT_FORMAT = GNU_FORMAT #--------------------------------------------------------- # tarfile constants #--------------------------------------------------------- -SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, # file types that tarfile - SYMTYPE, DIRTYPE, FIFOTYPE, # can cope with. +# File types that tarfile supports: +SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, + SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, CHRTYPE, BLKTYPE, GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, GNUTYPE_SPARSE) -REGULAR_TYPES = (REGTYPE, AREGTYPE, # file types that somehow - CONTTYPE, GNUTYPE_SPARSE) # represent regular files +# File types that will be treated as a regular file. +REGULAR_TYPES = (REGTYPE, AREGTYPE, + CONTTYPE, GNUTYPE_SPARSE) + +# File types that are part of the GNU tar format. +GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, + GNUTYPE_SPARSE) + +# Fields from a pax header that override a TarInfo attribute. +PAX_FIELDS = ("path", "linkpath", "size", "mtime", + "uid", "gid", "uname", "gname") #--------------------------------------------------------- # Bits used in the mode field, values in octal. @@ -133,6 +152,13 @@ TOEXEC = 0001 # execute/search by other #--------------------------------------------------------- +# initialization +#--------------------------------------------------------- +ENCODING = sys.getfilesystemencoding() +if ENCODING is None: + ENCODING = "ascii" + +#--------------------------------------------------------- # Some useful functions #--------------------------------------------------------- @@ -141,6 +167,15 @@ """ return s[:length] + (length - len(s)) * NUL +def nts(s): + """Convert a null-terminated string field to a python string. + """ + # Use the string up to the first null char. + p = s.find("\0") + if p == -1: + return s + return s[:p] + def nti(s): """Convert a number field to a python number. """ @@ -148,7 +183,7 @@ # itn() below. if s[0] != chr(0200): try: - n = int(s.rstrip(NUL + " ") or "0", 8) + n = int(nts(s) or "0", 8) except ValueError: raise HeaderError("invalid header") else: @@ -158,7 +193,7 @@ n += ord(s[i + 1]) return n -def itn(n, digits=8, posix=False): +def itn(n, digits=8, format=DEFAULT_FORMAT): """Convert a python number to a number field. """ # POSIX 1003.1-1988 requires numbers to be encoded as a string of @@ -170,7 +205,7 @@ if 0 <= n < 8 ** (digits - 1): s = "%0*o" % (digits - 1, n) + NUL else: - if posix: + if format != GNU_FORMAT or n >= 256 ** (digits - 1): raise ValueError("overflow in number field") if n < 0: @@ -516,7 +551,10 @@ buf = self.__read(self.bufsize) if not buf: break - buf = self.cmp.decompress(buf) + try: + buf = self.cmp.decompress(buf) + except IOError: + raise ReadError("invalid compressed data") t.append(buf) c += len(buf) t = "".join(t) @@ -577,6 +615,7 @@ def __init__(self, fileobj, mode): self.fileobj = fileobj self.mode = mode + self.name = getattr(self.fileobj, "name", None) self.init() def init(self): @@ -849,8 +888,8 @@ """Construct a TarInfo object. name is the optional name of the member. """ - self.name = name # member name (dirnames must end with '/') - self.mode = 0666 # file permissions + self.name = name # member name + self.mode = 0644 # file permissions self.uid = 0 # user id self.gid = 0 # group id self.size = 0 # file size @@ -858,17 +897,274 @@ self.chksum = 0 # header checksum self.type = REGTYPE # member type self.linkname = "" # link name - self.uname = "user" # user name - self.gname = "group" # group name + self.uname = "root" # user name + self.gname = "root" # group name self.devmajor = 0 # device major number self.devminor = 0 # device minor number self.offset = 0 # the tar header starts here self.offset_data = 0 # the file's data starts here + self.pax_headers = {} # pax header information + + # In pax headers the "name" and "linkname" field are called + # "path" and "linkpath". + def _getpath(self): + return self.name + def _setpath(self, name): + self.name = name + path = property(_getpath, _setpath) + + def _getlinkpath(self): + return self.linkname + def _setlinkpath(self, linkname): + self.linkname = linkname + linkpath = property(_getlinkpath, _setlinkpath) + def __repr__(self): return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) + def get_info(self): + """Return the TarInfo's attributes as a dictionary. + """ + info = { + "name": normpath(self.name), + "mode": self.mode & 07777, + "uid": self.uid, + "gid": self.gid, + "size": self.size, + "mtime": self.mtime, + "chksum": self.chksum, + "type": self.type, + "linkname": normpath(self.linkname) if self.linkname else "", + "uname": self.uname, + "gname": self.gname, + "devmajor": self.devmajor, + "devminor": self.devminor + } + + if info["type"] == DIRTYPE and not info["name"].endswith("/"): + info["name"] += "/" + + return info + + def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING): + """Return a tar header as a string of 512 byte blocks. + """ + if format == USTAR_FORMAT: + return self.create_ustar_header() + elif format == GNU_FORMAT: + return self.create_gnu_header() + elif format == PAX_FORMAT: + return self.create_pax_header(encoding) + else: + raise ValueError("invalid format") + + def create_ustar_header(self): + """Return the object as a ustar header block. + """ + info = self.get_info() + info["magic"] = POSIX_MAGIC + + if len(info["linkname"]) > LENGTH_LINK: + raise ValueError("linkname is too long") + + if len(info["name"]) > LENGTH_NAME: + info["prefix"], info["name"] = self._posix_split_name(info["name"]) + + return self._create_header(info, USTAR_FORMAT) + + def create_gnu_header(self): + """Return the object as a GNU header block sequence. + """ + info = self.get_info() + info["magic"] = GNU_MAGIC + + buf = "" + if len(info["linkname"]) > LENGTH_LINK: + buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK) + + if len(info["name"]) > LENGTH_NAME: + buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME) + + return buf + self._create_header(info, GNU_FORMAT) + + def create_pax_header(self, encoding): + """Return the object as a ustar header block. If it cannot be + represented this way, prepend a pax extended header sequence + with supplement information. + """ + info = self.get_info() + info["magic"] = POSIX_MAGIC + pax_headers = self.pax_headers.copy() + + # Test string fields for values that exceed the field length or cannot + # be represented in ASCII encoding. + for name, hname, length in ( + ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK), + ("uname", "uname", 32), ("gname", "gname", 32)): + + val = info[name].decode(encoding) + + # Try to encode the string as ASCII. + try: + val.encode("ascii") + except UnicodeEncodeError: + pax_headers[hname] = val + continue + + if len(val) > length: + if name == "name": + # Try to squeeze a longname in the prefix and name fields as in + # ustar format. + try: + info["prefix"], info["name"] = self._posix_split_name(info["name"]) + except ValueError: + pax_headers[hname] = val + else: + continue + else: + pax_headers[hname] = val + + # Test number fields for values that exceed the field limit or values + # that like to be stored as float. + for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): + val = info[name] + if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): + pax_headers[name] = unicode(val) + info[name] = 0 + + if pax_headers: + buf = self._create_pax_generic_header(pax_headers) + else: + buf = "" + + return buf + self._create_header(info, USTAR_FORMAT) + + @classmethod + def create_pax_global_header(cls, pax_headers, encoding): + """Return the object as a pax global header block sequence. + """ + new_headers = {} + for key, val in pax_headers.items(): + key = cls._to_unicode(key, encoding) + val = cls._to_unicode(val, encoding) + new_headers[key] = val + return cls._create_pax_generic_header(new_headers, type=XGLTYPE) + + @staticmethod + def _to_unicode(value, encoding): + if isinstance(value, unicode): + return value + elif isinstance(value, (int, float)): + return unicode(value) + elif isinstance(value, str): + return unicode(value, encoding) + else: + raise ValueError("unable to convert to unicode: %r" % value) + + def _posix_split_name(self, name): + """Split a name longer than 100 chars into a prefix + and a name part. + """ + prefix = name[:LENGTH_PREFIX + 1] + while prefix and prefix[-1] != "/": + prefix = prefix[:-1] + + name = name[len(prefix):] + prefix = prefix[:-1] + + if not prefix or len(name) > LENGTH_NAME: + raise ValueError("name is too long") + return prefix, name + + @staticmethod + def _create_header(info, format): + """Return a header block. info is a dictionary with file + information, format must be one of the *_FORMAT constants. + """ + parts = [ + stn(info.get("name", ""), 100), + itn(info.get("mode", 0) & 07777, 8, format), + itn(info.get("uid", 0), 8, format), + itn(info.get("gid", 0), 8, format), + itn(info.get("size", 0), 12, format), + itn(info.get("mtime", 0), 12, format), + " ", # checksum field + info.get("type", REGTYPE), + stn(info.get("linkname", ""), 100), + stn(info.get("magic", ""), 8), + stn(info.get("uname", ""), 32), + stn(info.get("gname", ""), 32), + itn(info.get("devmajor", 0), 8, format), + itn(info.get("devminor", 0), 8, format), + stn(info.get("prefix", ""), 155) + ] + + buf = struct.pack("%ds" % BLOCKSIZE, "".join(parts)) + chksum = calc_chksums(buf[-BLOCKSIZE:])[0] + buf = buf[:-364] + "%06o\0" % chksum + buf[-357:] + return buf + + @staticmethod + def _create_payload(payload): + """Return the string payload filled with zero bytes + up to the next 512 byte border. + """ + blocks, remainder = divmod(len(payload), BLOCKSIZE) + if remainder > 0: + payload += (BLOCKSIZE - remainder) * NUL + return payload + + @classmethod + def _create_gnu_long_header(cls, name, type): + """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence + for name. + """ + name += NUL + + info = {} + info["name"] = "././@LongLink" + info["type"] = type + info["size"] = len(name) + info["magic"] = GNU_MAGIC + + # create extended header + name blocks. + return cls._create_header(info, USTAR_FORMAT) + \ + cls._create_payload(name) + + @classmethod + def _create_pax_generic_header(cls, pax_headers, type=XHDTYPE): + """Return a POSIX.1-2001 extended or global header sequence + that contains a list of keyword, value pairs. The values + must be unicode objects. + """ + records = [] + for keyword, value in pax_headers.items(): + keyword = keyword.encode("utf8") + value = value.encode("utf8") + l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n' + n = p = 0 + while True: + n = l + len(str(p)) + if n == p: + break + p = n + records.append("%d %s=%s\n" % (p, keyword, value)) + records = "".join(records) + + # We use a hardcoded "././@PaxHeader" name like star does + # instead of the one that POSIX recommends. + info = {} + info["name"] = "././@PaxHeader" + info["type"] = type + info["size"] = len(records) + info["magic"] = POSIX_MAGIC + + # Create pax header + record blocks. + return cls._create_header(info, USTAR_FORMAT) + \ + cls._create_payload(records) + @classmethod def frombuf(cls, buf): """Construct a TarInfo object from a 512 byte string buffer. @@ -882,125 +1178,251 @@ if chksum not in calc_chksums(buf): raise HeaderError("bad checksum") - tarinfo = cls() - tarinfo.buf = buf - tarinfo.name = buf[0:100].rstrip(NUL) - tarinfo.mode = nti(buf[100:108]) - tarinfo.uid = nti(buf[108:116]) - tarinfo.gid = nti(buf[116:124]) - tarinfo.size = nti(buf[124:136]) - tarinfo.mtime = nti(buf[136:148]) - tarinfo.chksum = chksum - tarinfo.type = buf[156:157] - tarinfo.linkname = buf[157:257].rstrip(NUL) - tarinfo.uname = buf[265:297].rstrip(NUL) - tarinfo.gname = buf[297:329].rstrip(NUL) - tarinfo.devmajor = nti(buf[329:337]) - tarinfo.devminor = nti(buf[337:345]) - prefix = buf[345:500].rstrip(NUL) + obj = cls() + obj.buf = buf + obj.name = nts(buf[0:100]) + obj.mode = nti(buf[100:108]) + obj.uid = nti(buf[108:116]) + obj.gid = nti(buf[116:124]) + obj.size = nti(buf[124:136]) + obj.mtime = nti(buf[136:148]) + obj.chksum = chksum + obj.type = buf[156:157] + obj.linkname = nts(buf[157:257]) + obj.uname = nts(buf[265:297]) + obj.gname = nts(buf[297:329]) + obj.devmajor = nti(buf[329:337]) + obj.devminor = nti(buf[337:345]) + prefix = nts(buf[345:500]) - if prefix and not tarinfo.issparse(): - tarinfo.name = prefix + "/" + tarinfo.name + # Old V7 tar format represents a directory as a regular + # file with a trailing slash. + if obj.type == AREGTYPE and obj.name.endswith("/"): + obj.type = DIRTYPE - return tarinfo + # Remove redundant slashes from directories. + if obj.isdir(): + obj.name = obj.name.rstrip("/") + + # Reconstruct a ustar longname. + if prefix and obj.type not in GNU_TYPES: + obj.name = prefix + "/" + obj.name + return obj - def tobuf(self, posix=False): - """Return a tar header as a string of 512 byte blocks. + @classmethod + def fromtarfile(cls, tarfile): + """Return the next TarInfo object from TarFile object + tarfile. """ - buf = "" - type = self.type - prefix = "" + buf = tarfile.fileobj.read(BLOCKSIZE) + if not buf: + return + obj = cls.frombuf(buf) + obj.offset = tarfile.fileobj.tell() - BLOCKSIZE + return obj._proc_member(tarfile) - if self.name.endswith("/"): - type = DIRTYPE + #-------------------------------------------------------------------------- + # The following are methods that are called depending on the type of a + # member. The entry point is _proc_member() which can be overridden in a + # subclass to add custom _proc_*() methods. A _proc_*() method MUST + # implement the following + # operations: + # 1. Set self.offset_data to the position where the data blocks begin, + # if there is data that follows. + # 2. Set tarfile.offset to the position where the next member's header will + # begin. + # 3. Return self or another valid TarInfo object. + def _proc_member(self, tarfile): + """Choose the right processing method depending on + the type and call it. + """ + if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): + return self._proc_gnulong(tarfile) + elif self.type == GNUTYPE_SPARSE: + return self._proc_sparse(tarfile) + elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE): + return self._proc_pax(tarfile) + else: + return self._proc_builtin(tarfile) + + def _proc_builtin(self, tarfile): + """Process a builtin type or an unknown type which + will be treated as a regular file. + """ + self.offset_data = tarfile.fileobj.tell() + offset = self.offset_data + if self.isreg() or self.type not in SUPPORTED_TYPES: + # Skip the following data blocks. + offset += self._block(self.size) + tarfile.offset = offset - if type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): - # Prevent "././@LongLink" from being normalized. - name = self.name - else: - name = normpath(self.name) + # Patch the TarInfo object with saved extended + # header information. + for keyword, value in tarfile.pax_headers.items(): + if keyword in PAX_FIELDS: + setattr(self, keyword, value) + self.pax_headers[keyword] = value - if type == DIRTYPE: - # directories should end with '/' - name += "/" + return self - linkname = self.linkname - if linkname: - # if linkname is empty we end up with a '.' - linkname = normpath(linkname) + def _proc_gnulong(self, tarfile): + """Process the blocks that hold a GNU longname + or longlink member. + """ + buf = tarfile.fileobj.read(self._block(self.size)) - if posix: - if self.size > MAXSIZE_MEMBER: - raise ValueError("file is too large (>= 8 GB)") + # Fetch the next header and process it. + b = tarfile.fileobj.read(BLOCKSIZE) + t = self.frombuf(b) + t.offset = self.offset + next = t._proc_member(tarfile) - if len(self.linkname) > LENGTH_LINK: - raise ValueError("linkname is too long (>%d)" % (LENGTH_LINK)) + # Patch the TarInfo object from the next header with + # the longname information. + next.offset = self.offset + if self.type == GNUTYPE_LONGNAME: + next.name = buf.rstrip(NUL) + elif self.type == GNUTYPE_LONGLINK: + next.linkname = buf.rstrip(NUL) - if len(name) > LENGTH_NAME: - prefix = name[:LENGTH_PREFIX + 1] - while prefix and prefix[-1] != "/": - prefix = prefix[:-1] + return next - name = name[len(prefix):] - prefix = prefix[:-1] + def _proc_sparse(self, tarfile): + """Process a GNU sparse header plus extra headers. + """ + buf = self.buf + sp = _ringbuffer() + pos = 386 + lastpos = 0 + realpos = 0 + # There are 4 possible sparse structs in the + # first header. + for i in xrange(4): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + if offset > lastpos: + sp.append(_hole(lastpos, offset - lastpos)) + sp.append(_data(offset, numbytes, realpos)) + realpos += numbytes + lastpos = offset + numbytes + pos += 24 - if not prefix or len(name) > LENGTH_NAME: - raise ValueError("name is too long") + isextended = ord(buf[482]) + origsize = nti(buf[483:495]) - else: - if len(self.linkname) > LENGTH_LINK: - buf += self._create_gnulong(self.linkname, GNUTYPE_LONGLINK) + # If the isextended flag is given, + # there are extra headers to process. + while isextended == 1: + buf = tarfile.fileobj.read(BLOCKSIZE) + pos = 0 + for i in xrange(21): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + if offset > lastpos: + sp.append(_hole(lastpos, offset - lastpos)) + sp.append(_data(offset, numbytes, realpos)) + realpos += numbytes + lastpos = offset + numbytes + pos += 24 + isextended = ord(buf[504]) - if len(name) > LENGTH_NAME: - buf += self._create_gnulong(name, GNUTYPE_LONGNAME) + if lastpos < origsize: + sp.append(_hole(lastpos, origsize - lastpos)) - parts = [ - stn(name, 100), - itn(self.mode & 07777, 8, posix), - itn(self.uid, 8, posix), - itn(self.gid, 8, posix), - itn(self.size, 12, posix), - itn(self.mtime, 12, posix), - " ", # checksum field - type, - stn(self.linkname, 100), - stn(MAGIC, 6), - stn(VERSION, 2), - stn(self.uname, 32), - stn(self.gname, 32), - itn(self.devmajor, 8, posix), - itn(self.devminor, 8, posix), - stn(prefix, 155) - ] + self.sparse = sp - buf += struct.pack("%ds" % BLOCKSIZE, "".join(parts)) - chksum = calc_chksums(buf[-BLOCKSIZE:])[0] - buf = buf[:-364] + "%06o\0" % chksum + buf[-357:] - self.buf = buf - return buf + self.offset_data = tarfile.fileobj.tell() + tarfile.offset = self.offset_data + self._block(self.size) + self.size = origsize - def _create_gnulong(self, name, type): - """Create a GNU longname/longlink header from name. - It consists of an extended tar header, with the length - of the longname as size, followed by data blocks, - which contain the longname as a null terminated string. - """ - name += NUL + return self - tarinfo = self.__class__() - tarinfo.name = "././@LongLink" - tarinfo.type = type - tarinfo.mode = 0 - tarinfo.size = len(name) + def _proc_pax(self, tarfile): + """Process an extended or global header as described in + POSIX.1-2001. + """ + # Read the header information. + buf = tarfile.fileobj.read(self._block(self.size)) + + # A pax header stores supplemental information for either + # the following file (extended) or all following files + # (global). + if self.type == XGLTYPE: + pax_headers = tarfile.pax_headers + else: + pax_headers = tarfile.pax_headers.copy() + + # Fields in POSIX.1-2001 that are numbers, all other fields + # are treated as UTF-8 strings. + type_mapping = { + "atime": float, + "ctime": float, + "mtime": float, + "uid": int, + "gid": int, + "size": int + } + + # Parse pax header information. A record looks like that: + # "%d %s=%s\n" % (length, keyword, value). length is the size + # of the complete record including the length field itself and + # the newline. + regex = re.compile(r"(\d+) ([^=]+)=", re.U) + pos = 0 + while True: + match = regex.match(buf, pos) + if not match: + break - # create extended header - buf = tarinfo.tobuf() - # create name blocks - buf += name - blocks, remainder = divmod(len(name), BLOCKSIZE) - if remainder > 0: - buf += (BLOCKSIZE - remainder) * NUL - return buf + length, keyword = match.groups() + length = int(length) + value = buf[match.end(2) + 1:match.start(1) + length - 1] + + keyword = keyword.decode("utf8") + keyword = keyword.encode(tarfile.encoding) + + value = value.decode("utf8") + if keyword in type_mapping: + try: + value = type_mapping[keyword](value) + except ValueError: + value = 0 + else: + value = value.encode(tarfile.encoding) + + pax_headers[keyword] = value + pos += length + + # Fetch the next header that will be patched with the + # supplement information from the pax header (extended + # only). + t = self.fromtarfile(tarfile) + + if self.type != XGLTYPE and t is not None: + # Patch the TarInfo object from the next header with + # the pax header's information. + for keyword, value in pax_headers.items(): + if keyword in PAX_FIELDS: + setattr(t, keyword, value) + pax_headers[keyword] = value + t.pax_headers = pax_headers.copy() + + return t + + def _block(self, count): + """Round up a byte count by BLOCKSIZE and return it, + e.g. _block(834) => 1024. + """ + blocks, remainder = divmod(count, BLOCKSIZE) + if remainder: + blocks += 1 + return blocks * BLOCKSIZE def isreg(self): return self.type in REGULAR_TYPES @@ -1040,12 +1462,18 @@ # messages (if debug >= 0). If > 0, errors # are passed to the caller as exceptions. - posix = False # If True, generates POSIX.1-1990-compliant - # archives (no GNU extensions!) + format = DEFAULT_FORMAT # The format to use when creating an archive. - fileobject = ExFileObject + encoding = ENCODING # Transfer UTF-8 strings from POSIX.1-2001 + # headers to this encoding. - def __init__(self, name=None, mode="r", fileobj=None): + tarinfo = TarInfo # The default TarInfo class to use. + + fileobject = ExFileObject # The default ExFileObject class to use. + + def __init__(self, name=None, mode="r", fileobj=None, format=None, + tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, + pax_headers=None, debug=None, errorlevel=None): """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to read from an existing archive, 'a' to append data to an existing file or 'w' to create a new file overwriting an existing one. `mode' @@ -1054,58 +1482,86 @@ can be determined, `mode' is overridden by `fileobj's mode. `fileobj' is not closed, when TarFile is closed. """ - self.name = os.path.abspath(name) - if len(mode) > 1 or mode not in "raw": raise ValueError("mode must be 'r', 'a' or 'w'") - self._mode = mode - self.mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode] + self.mode = mode + self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode] if not fileobj: - if self._mode == "a" and not os.path.exists(self.name): + if self.mode == "a" and not os.path.exists(name): # Create nonexistent files in append mode. - self._mode = "w" - self.mode = "wb" - fileobj = _open(self.name, self.mode) + self.mode = "w" + self._mode = "wb" + fileobj = _open(name, self._mode) self._extfileobj = False else: - if self.name is None and hasattr(fileobj, "name"): - self.name = os.path.abspath(fileobj.name) + if name is None and hasattr(fileobj, "name"): + name = fileobj.name if hasattr(fileobj, "mode"): - self.mode = fileobj.mode + self._mode = fileobj.mode self._extfileobj = True + self.name = os.path.abspath(name) self.fileobj = fileobj - # Init datastructures + # Init attributes. + if format is not None: + self.format = format + if tarinfo is not None: + self.tarinfo = tarinfo + if dereference is not None: + self.dereference = dereference + if ignore_zeros is not None: + self.ignore_zeros = ignore_zeros + if encoding is not None: + self.encoding = encoding + if debug is not None: + self.debug = debug + if errorlevel is not None: + self.errorlevel = errorlevel + + # Init datastructures. self.closed = False self.members = [] # list of members as TarInfo objects self._loaded = False # flag if all members have been read self.offset = 0 # current position in the archive file self.inodes = {} # dictionary caching the inodes of # archive members already added + self.pax_headers = {} # save contents of global pax headers - if self._mode == "r": + if self.mode == "r": self.firstmember = None self.firstmember = self.next() - if self._mode == "a": + if self.mode == "a": # Move to the end of the archive, # before the first empty block. self.firstmember = None while True: - try: - tarinfo = self.next() - except ReadError: - self.fileobj.seek(0) - break - if tarinfo is None: + if self.next() is None: if self.offset > 0: self.fileobj.seek(- BLOCKSIZE, 1) break - if self._mode in "aw": + if self.mode in "aw": self._loaded = True + if pax_headers: + buf = self.tarinfo.create_pax_global_header( + pax_headers.copy(), self.encoding) + self.fileobj.write(buf) + self.offset += len(buf) + + def _getposix(self): + return self.format == USTAR_FORMAT + def _setposix(self, value): + import warnings + warnings.warn("use the format attribute instead", DeprecationWarning) + if value: + self.format = USTAR_FORMAT + else: + self.format = GNU_FORMAT + posix = property(_getposix, _setposix) + #-------------------------------------------------------------------------- # Below are the classmethods which act as alternate constructors to the # TarFile class. The open() method is the only one that is needed for @@ -1118,7 +1574,7 @@ # by adding it to the mapping in OPEN_METH. @classmethod - def open(cls, name=None, mode="r", fileobj=None, bufsize=20*512): + def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs): """Open a tar archive for reading, writing or appending. Return an appropriate TarFile class. @@ -1151,8 +1607,8 @@ if fileobj is not None: saved_pos = fileobj.tell() try: - return func(name, "r", fileobj) - except (ReadError, CompressionError): + return func(name, "r", fileobj, **kwargs) + except (ReadError, CompressionError) as e: if fileobj is not None: fileobj.seek(saved_pos) continue @@ -1169,7 +1625,7 @@ func = getattr(cls, cls.OPEN_METH[comptype]) else: raise CompressionError("unknown compression type %r" % comptype) - return func(name, filemode, fileobj) + return func(name, filemode, fileobj, **kwargs) elif "|" in mode: filemode, comptype = mode.split("|", 1) @@ -1180,25 +1636,26 @@ raise ValueError("mode must be 'r' or 'w'") t = cls(name, filemode, - _Stream(name, filemode, comptype, fileobj, bufsize)) + _Stream(name, filemode, comptype, fileobj, bufsize), + **kwargs) t._extfileobj = False return t elif mode in "aw": - return cls.taropen(name, mode, fileobj) + return cls.taropen(name, mode, fileobj, **kwargs) raise ValueError("undiscernible mode") @classmethod - def taropen(cls, name, mode="r", fileobj=None): + def taropen(cls, name, mode="r", fileobj=None, **kwargs): """Open uncompressed tar archive name for reading or writing. """ if len(mode) > 1 or mode not in "raw": raise ValueError("mode must be 'r', 'a' or 'w'") - return cls(name, mode, fileobj) + return cls(name, mode, fileobj, **kwargs) @classmethod - def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9): + def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): """Open gzip compressed tar archive name for reading or writing. Appending is not allowed. """ @@ -1216,14 +1673,15 @@ try: t = cls.taropen(name, mode, - gzip.GzipFile(name, mode, compresslevel, fileobj)) + gzip.GzipFile(name, mode, compresslevel, fileobj), + **kwargs) except IOError: raise ReadError("not a gzip file") t._extfileobj = False return t @classmethod - def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9): + def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): """Open bzip2 compressed tar archive name for reading or writing. Appending is not allowed. """ @@ -1241,7 +1699,7 @@ fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) try: - t = cls.taropen(name, mode, fileobj) + t = cls.taropen(name, mode, fileobj, **kwargs) except IOError: raise ReadError("not a bzip2 file") t._extfileobj = False @@ -1264,7 +1722,7 @@ if self.closed: return - if self._mode in "aw": + if self.mode in "aw": self.fileobj.write(NUL * (BLOCKSIZE * 2)) self.offset += (BLOCKSIZE * 2) # fill up the end with zero-blocks @@ -1330,7 +1788,8 @@ # Now, fill the TarInfo object with # information specific for the file. - tarinfo = TarInfo() + tarinfo = self.tarinfo() + tarinfo.tarfile = self # Use os.stat or os.lstat, depending on platform # and if symlinks shall be resolved. @@ -1346,8 +1805,8 @@ stmd = statres.st_mode if stat.S_ISREG(stmd): inode = (statres.st_ino, statres.st_dev) - if not self.dereference and \ - statres.st_nlink > 1 and inode in self.inodes: + if not self.dereference and statres.st_nlink > 1 and \ + inode in self.inodes and arcname != self.inodes[inode]: # Is it a hardlink to an already # archived file? type = LNKTYPE @@ -1424,7 +1883,7 @@ print("%d-%02d-%02d %02d:%02d:%02d" \ % time.localtime(tarinfo.mtime)[:6], end=' ') - print(tarinfo.name, end=' ') + print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') if verbose: if tarinfo.issym(): @@ -1456,7 +1915,7 @@ if recursive: if arcname == ".": arcname = "" - for f in os.listdir("."): + for f in os.listdir(name): self.add(f, os.path.join(arcname, f)) return @@ -1495,7 +1954,7 @@ tarinfo = copy.copy(tarinfo) - buf = tarinfo.tobuf(self.posix) + buf = tarinfo.tobuf(self.format, self.encoding) self.fileobj.write(buf) self.offset += len(buf) @@ -1527,7 +1986,7 @@ # Extract directory with a safe mode, so that # all files below can be extracted as well. try: - os.makedirs(os.path.join(path, tarinfo.name), 0777) + os.makedirs(os.path.join(path, tarinfo.name), 0700) except EnvironmentError: pass directories.append(tarinfo) @@ -1559,10 +2018,10 @@ """ self._check("r") - if isinstance(member, TarInfo): - tarinfo = member - else: + if isinstance(member, basestring): tarinfo = self.getmember(member) + else: + tarinfo = member # Prepare the link target for makelink(). if tarinfo.islnk(): @@ -1595,10 +2054,10 @@ """ self._check("r") - if isinstance(member, TarInfo): - tarinfo = member - else: + if isinstance(member, basestring): tarinfo = self.getmember(member) + else: + tarinfo = member if tarinfo.isreg(): return self.fileobject(self, tarinfo) @@ -1811,20 +2270,11 @@ # Read the next block. self.fileobj.seek(self.offset) while True: - buf = self.fileobj.read(BLOCKSIZE) - if not buf: - return None - try: - tarinfo = TarInfo.frombuf(buf) - - # Set the TarInfo object's offset to the current position of the - # TarFile and set self.offset to the position where the data blocks - # should begin. - tarinfo.offset = self.offset - self.offset += BLOCKSIZE - - tarinfo = self.proc_member(tarinfo) + tarinfo = self.tarinfo.fromtarfile(self) + if tarinfo is None: + return + self.members.append(tarinfo) except HeaderError as e: if self.ignore_zeros: @@ -1837,149 +2287,11 @@ return None break - # Some old tar programs represent a directory as a regular - # file with a trailing slash. - if tarinfo.isreg() and tarinfo.name.endswith("/"): - tarinfo.type = DIRTYPE - - # Directory names should have a '/' at the end. - if tarinfo.isdir(): - tarinfo.name += "/" - - self.members.append(tarinfo) - return tarinfo - - #-------------------------------------------------------------------------- - # The following are methods that are called depending on the type of a - # member. The entry point is proc_member() which is called with a TarInfo - # object created from the header block from the current offset. The - # proc_member() method can be overridden in a subclass to add custom - # proc_*() methods. A proc_*() method MUST implement the following - # operations: - # 1. Set tarinfo.offset_data to the position where the data blocks begin, - # if there is data that follows. - # 2. Set self.offset to the position where the next member's header will - # begin. - # 3. Return tarinfo or another valid TarInfo object. - def proc_member(self, tarinfo): - """Choose the right processing method for tarinfo depending - on its type and call it. - """ - if tarinfo.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): - return self.proc_gnulong(tarinfo) - elif tarinfo.type == GNUTYPE_SPARSE: - return self.proc_sparse(tarinfo) - else: - return self.proc_builtin(tarinfo) - - def proc_builtin(self, tarinfo): - """Process a builtin type member or an unknown member - which will be treated as a regular file. - """ - tarinfo.offset_data = self.offset - if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES: - # Skip the following data blocks. - self.offset += self._block(tarinfo.size) - return tarinfo - - def proc_gnulong(self, tarinfo): - """Process the blocks that hold a GNU longname - or longlink member. - """ - buf = "" - count = tarinfo.size - while count > 0: - block = self.fileobj.read(BLOCKSIZE) - buf += block - self.offset += BLOCKSIZE - count -= BLOCKSIZE - - # Fetch the next header and process it. - b = self.fileobj.read(BLOCKSIZE) - t = TarInfo.frombuf(b) - t.offset = self.offset - self.offset += BLOCKSIZE - next = self.proc_member(t) - - # Patch the TarInfo object from the next header with - # the longname information. - next.offset = tarinfo.offset - if tarinfo.type == GNUTYPE_LONGNAME: - next.name = buf.rstrip(NUL) - elif tarinfo.type == GNUTYPE_LONGLINK: - next.linkname = buf.rstrip(NUL) - - return next - - def proc_sparse(self, tarinfo): - """Process a GNU sparse header plus extra headers. - """ - buf = tarinfo.buf - sp = _ringbuffer() - pos = 386 - lastpos = 0 - realpos = 0 - # There are 4 possible sparse structs in the - # first header. - for i in xrange(4): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - if offset > lastpos: - sp.append(_hole(lastpos, offset - lastpos)) - sp.append(_data(offset, numbytes, realpos)) - realpos += numbytes - lastpos = offset + numbytes - pos += 24 - - isextended = ord(buf[482]) - origsize = nti(buf[483:495]) - - # If the isextended flag is given, - # there are extra headers to process. - while isextended == 1: - buf = self.fileobj.read(BLOCKSIZE) - self.offset += BLOCKSIZE - pos = 0 - for i in xrange(21): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - if offset > lastpos: - sp.append(_hole(lastpos, offset - lastpos)) - sp.append(_data(offset, numbytes, realpos)) - realpos += numbytes - lastpos = offset + numbytes - pos += 24 - isextended = ord(buf[504]) - - if lastpos < origsize: - sp.append(_hole(lastpos, origsize - lastpos)) - - tarinfo.sparse = sp - - tarinfo.offset_data = self.offset - self.offset += self._block(tarinfo.size) - tarinfo.size = origsize - return tarinfo #-------------------------------------------------------------------------- # Little helper methods: - def _block(self, count): - """Round up a byte count by BLOCKSIZE and return it, - e.g. _block(834) => 1024. - """ - blocks, remainder = divmod(count, BLOCKSIZE) - if remainder: - blocks += 1 - return blocks * BLOCKSIZE - def _getmember(self, name, tarinfo=None): """Find an archive member by name from bottom to top. If tarinfo is given, it is used as the starting point. @@ -2012,8 +2324,8 @@ """ if self.closed: raise IOError("%s is closed" % self.__class__.__name__) - if mode is not None and self._mode not in mode: - raise IOError("bad operation for mode %r" % self._mode) + if mode is not None and self.mode not in mode: + raise IOError("bad operation for mode %r" % self.mode) def __iter__(self): """Provide an iterator object. Modified: python/branches/p3yk/Lib/telnetlib.py ============================================================================== --- python/branches/p3yk/Lib/telnetlib.py (original) +++ python/branches/p3yk/Lib/telnetlib.py Fri Apr 27 21:54:29 2007 @@ -184,7 +184,7 @@ """ - def __init__(self, host=None, port=0): + def __init__(self, host=None, port=0, timeout=None): """Constructor. When called without arguments, create an unconnected instance. @@ -195,6 +195,7 @@ self.debuglevel = DEBUGLEVEL self.host = host self.port = port + self.timeout = timeout self.sock = None self.rawq = '' self.irawq = 0 @@ -205,9 +206,9 @@ self.sbdataq = '' self.option_callback = None if host is not None: - self.open(host, port) + self.open(host, port, timeout) - def open(self, host, port=0): + def open(self, host, port=0, timeout=None): """Connect to a host. The optional second argument is the port number, which @@ -221,20 +222,9 @@ port = TELNET_PORT self.host = host self.port = port - msg = "getaddrinfo returns an empty list" - for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - self.sock = socket.socket(af, socktype, proto) - self.sock.connect(sa) - except socket.error as msg: - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg + if timeout is not None: + self.timeout = timeout + self.sock = socket.create_connection((host, port), self.timeout) def __del__(self): """Destructor -- close the connection.""" @@ -661,7 +651,7 @@ port = socket.getservbyname(portstr, 'tcp') tn = Telnet() tn.set_debuglevel(debuglevel) - tn.open(host, port) + tn.open(host, port, timeout=0.5) tn.interact() tn.close() Modified: python/branches/p3yk/Lib/tempfile.py ============================================================================== --- python/branches/p3yk/Lib/tempfile.py (original) +++ python/branches/p3yk/Lib/tempfile.py Fri Apr 27 21:54:29 2007 @@ -19,6 +19,7 @@ __all__ = [ "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces + "SpooledTemporaryFile", "mkstemp", "mkdtemp", # low level safe interfaces "mktemp", # deprecated unsafe interface "TMP_MAX", "gettempprefix", # constants @@ -37,6 +38,11 @@ import Carbon.Folders as _Folders try: + from cStringIO import StringIO as _StringIO +except: + from StringIO import StringIO as _StringIO + +try: import fcntl as _fcntl except ImportError: def _set_cloexec(fd): @@ -114,7 +120,7 @@ characters = ("abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + - "0123456789-_") + "0123456789_") def __init__(self): self.mutex = _allocate_lock() @@ -372,10 +378,11 @@ remove the file when it is no longer needed. """ - def __init__(self, file, name): + def __init__(self, file, name, delete=True): self.file = file self.name = name self.close_called = False + self.delete = delete def __getattr__(self, name): file = self.__dict__['file'] @@ -400,23 +407,25 @@ if not self.close_called: self.close_called = True self.file.close() - self.unlink(self.name) + if self.delete: + self.unlink(self.name) def __del__(self): self.close() def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="", - prefix=template, dir=None): + prefix=template, dir=None, delete=True): """Create and return a temporary file. Arguments: 'prefix', 'suffix', 'dir' -- as for mkstemp. 'mode' -- the mode argument to os.fdopen (default "w+b"). 'bufsize' -- the buffer size argument to os.fdopen (default -1). + 'delete' -- whether the file is deleted on close (default True). The file is created as mkstemp() would do it. Returns an object with a file-like interface; the name of the file is accessible as file.name. The file will be automatically deleted - when it is closed. + when it is closed unless the 'delete' argument is set to False. """ if dir is None: @@ -429,12 +438,12 @@ # Setting O_TEMPORARY in the flags causes the OS to delete # the file when it is closed. This is only supported by Windows. - if _os.name == 'nt': + if _os.name == 'nt' and delete: flags |= _os.O_TEMPORARY (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) file = _os.fdopen(fd, mode, bufsize) - return _TemporaryFileWrapper(file, name) + return _TemporaryFileWrapper(file, name, delete) if _os.name != 'posix' or _os.sys.platform == 'cygwin': # On non-POSIX and Cygwin systems, assume that we cannot unlink a file @@ -470,3 +479,111 @@ except: _os.close(fd) raise + +class SpooledTemporaryFile: + """Temporary file wrapper, specialized to switch from + StringIO to a real file when it exceeds a certain size or + when a fileno is needed. + """ + _rolled = False + + def __init__(self, max_size=0, mode='w+b', bufsize=-1, + suffix="", prefix=template, dir=None): + self._file = _StringIO() + self._max_size = max_size + self._rolled = False + self._TemporaryFileArgs = (mode, bufsize, suffix, prefix, dir) + + def _check(self, file): + if self._rolled: return + max_size = self._max_size + if max_size and file.tell() > max_size: + self.rollover() + + def rollover(self): + if self._rolled: return + file = self._file + newfile = self._file = TemporaryFile(*self._TemporaryFileArgs) + del self._TemporaryFileArgs + + newfile.write(file.getvalue()) + newfile.seek(file.tell(), 0) + + self._rolled = True + + # file protocol + def __iter__(self): + return self._file.__iter__() + + def close(self): + self._file.close() + + @property + def closed(self): + return self._file.closed + + @property + def encoding(self): + return self._file.encoding + + def fileno(self): + self.rollover() + return self._file.fileno() + + def flush(self): + self._file.flush() + + def isatty(self): + return self._file.isatty() + + @property + def mode(self): + return self._file.mode + + @property + def name(self): + return self._file.name + + @property + def newlines(self): + return self._file.newlines + + def next(self): + return self._file.next + + def read(self, *args): + return self._file.read(*args) + + def readline(self, *args): + return self._file.readline(*args) + + def readlines(self, *args): + return self._file.readlines(*args) + + def seek(self, *args): + self._file.seek(*args) + + @property + def softspace(self): + return self._file.softspace + + def tell(self): + return self._file.tell() + + def truncate(self): + self._file.truncate() + + def write(self, s): + file = self._file + rv = file.write(s) + self._check(file) + return rv + + def writelines(self, iterable): + file = self._file + rv = file.writelines(iterable) + self._check(file) + return rv + + def xreadlines(self, *args): + return self._file.xreadlines(*args) Modified: python/branches/p3yk/Lib/test/README ============================================================================== --- python/branches/p3yk/Lib/test/README (original) +++ python/branches/p3yk/Lib/test/README Fri Apr 27 21:54:29 2007 @@ -15,7 +15,7 @@ one of these options. Each option requires writing a test module using the conventions of the selected option: - - PyUnit_ based tests + - unittest_ based tests - doctest_ based tests - "traditional" Python test modules @@ -28,31 +28,34 @@ able to refer to the C and Python code in the CVS repository when writing your regression test cases. -.. _PyUnit: .. _unittest: http://www.python.org/doc/current/lib/module-unittest.html .. _doctest: http://www.python.org/doc/current/lib/module-doctest.html -PyUnit based tests +unittest-based tests ------------------ -The PyUnit_ framework is based on the ideas of unit testing as espoused +The unittest_ framework is based on the ideas of unit testing as espoused by Kent Beck and the `Extreme Programming`_ (XP) movement. The specific interface provided by the framework is tightly based on the JUnit_ Java implementation of Beck's original SmallTalk test framework. Please see the documentation of the unittest_ module for detailed information on -the interface and general guidelines on writing PyUnit based tests. +the interface and general guidelines on writing unittest-based tests. -The test_support helper module provides two functions for use by -PyUnit based tests in the Python regression testing framework: - -- ``run_unittest()`` takes a ``unittest.TestCase`` derived class as a - parameter and runs the tests defined in that class - -- ``run_suite()`` takes a populated ``TestSuite`` instance and runs the - tests +The test_support helper module provides a function for use by +unittest-based tests in the Python regression testing framework, +``run_unittest()``. This is the primary way of running tests in the +standard library. You can pass it any number of the following: + +- classes derived from or instances of ``unittest.TestCase`` or + ``unittest.TestSuite``. These will be handed off to unittest for + converting into a proper TestSuite instance. + +- a string; this must be a key in sys.modules. The module associated with + that string will be scanned by ``unittest.TestLoader.loadTestsFromModule``. + This is usually seen as ``test_support.run_unittest(__name__)`` in a test + module's ``test_main()`` function. This has the advantage of picking up + new tests automatically, without you having to add each new test case + manually. -``run_suite()`` is preferred because unittest files typically grow multiple -test classes, and you might as well be prepared. - All test methods in the Python regression framework have names that start with "``test_``" and use lower-case names with words separated with underscores. @@ -63,7 +66,7 @@ latter information makes it easier to find the source for the test than the docstring. -All PyUnit-based tests in the Python test suite use boilerplate that +All unittest-based tests in the Python test suite use boilerplate that looks like this (with minor variations):: import unittest @@ -97,11 +100,7 @@ ...etc... def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(MyTestCase1)) - suite.addTest(unittest.makeSuite(MyTestCase2)) - ...add more suites... - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() @@ -415,7 +414,7 @@ This is rarely required with the "traditional" Python tests, and you shouldn't create a module global with name test_main unless you're specifically exploiting this gimmick. This usage does - prove useful with PyUnit-based tests as well, however; defining + prove useful with unittest-based tests as well, however; defining a ``test_main()`` which is run by regrtest and a script-stub in the test module ("``if __name__ == '__main__': test_main()``") allows the test to be used like any other Python test and also work 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 Fri Apr 27 21:54:29 2007 @@ -4,15 +4,16 @@ class Y(object): pass -class type_with_modifiable_dict(Y, type): +class type_with_modifiable_dict(type, Y): pass 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. + """This class has its __dict__ attribute indirectly + exposed via the __dict__ getter/setter of Y. """ if __name__ == '__main__': - del MyClass.__dict__ # if we set tp_dict to NULL, + dictattr = Y.__dict__['__dict__'] + dictattr.__delete__(MyClass) # if we set tp_dict to NULL, print(MyClass) # doing anything with MyClass segfaults Deleted: /python/branches/p3yk/Lib/test/output/test_operations ============================================================================== --- /python/branches/p3yk/Lib/test/output/test_operations Fri Apr 27 21:54:29 2007 +++ (empty file) @@ -1,19 +0,0 @@ -test_operations -3. Operations -XXX Mostly not yet implemented -3.1 Dictionary lookups fail if __cmp__() raises an exception -raising error -d[x2] = 2: caught the RuntimeError outside -raising error -z = d[x2]: caught the RuntimeError outside -raising error -x2 in d: caught the RuntimeError outside -raising error -d.get(x2): caught the RuntimeError outside -raising error -d.setdefault(x2, 42): caught the RuntimeError outside -raising error -d.pop(x2): caught the RuntimeError outside -raising error -d.update({x2: 2}): caught the RuntimeError outside -resize bugs not triggered. Deleted: /python/branches/p3yk/Lib/test/output/test_popen2 ============================================================================== --- /python/branches/p3yk/Lib/test/output/test_popen2 Fri Apr 27 21:54:29 2007 +++ (empty file) @@ -1,9 +0,0 @@ -test_popen2 -Test popen2 module: -testing popen2... -testing popen3... -All OK -Testing os module: -testing popen2... -testing popen3... -All OK Deleted: /python/branches/p3yk/Lib/test/output/test_pty ============================================================================== --- /python/branches/p3yk/Lib/test/output/test_pty Fri Apr 27 21:54:29 2007 +++ (empty file) @@ -1,3 +0,0 @@ -test_pty -I wish to buy a fish license. -For my pet fish, Eric. Deleted: /python/branches/p3yk/Lib/test/output/test_pyexpat ============================================================================== --- /python/branches/p3yk/Lib/test/output/test_pyexpat Fri Apr 27 21:54:29 2007 +++ (empty file) @@ -1,110 +0,0 @@ -test_pyexpat -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -PI: - 'xml-stylesheet' 'href="stylesheet.css"' -Comment: - ' comment data ' -Notation declared: ('notation', None, 'notation.jpeg', None) -Unparsed entity decl: - ('unparsed_entity', None, 'entity.file', None, 'notation') -Start element: - 'root' {'attr1': 'value1', 'attr2': 'value2\xe1\xbd\x80'} -NS decl: - 'myns' 'http://www.python.org/namespace' -Start element: - 'http://www.python.org/namespace!subelement' {} -Character data: - 'Contents of subelements' -End element: - 'http://www.python.org/namespace!subelement' -End of NS decl: - 'myns' -Start element: - 'sub2' {} -Start of CDATA section -Character data: - 'contents of CDATA section' -End of CDATA section -End element: - 'sub2' -External entity ref: (None, 'entity.file', None) -End element: - 'root' -PI: - u'xml-stylesheet' u'href="stylesheet.css"' -Comment: - u' comment data ' -Notation declared: (u'notation', None, u'notation.jpeg', None) -Unparsed entity decl: - (u'unparsed_entity', None, u'entity.file', None, u'notation') -Start element: - u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'} -NS decl: - u'myns' u'http://www.python.org/namespace' -Start element: - u'http://www.python.org/namespace!subelement' {} -Character data: - u'Contents of subelements' -End element: - u'http://www.python.org/namespace!subelement' -End of NS decl: - u'myns' -Start element: - u'sub2' {} -Start of CDATA section -Character data: - u'contents of CDATA section' -End of CDATA section -End element: - u'sub2' -External entity ref: (None, u'entity.file', None) -End element: - u'root' -PI: - u'xml-stylesheet' u'href="stylesheet.css"' -Comment: - u' comment data ' -Notation declared: (u'notation', None, u'notation.jpeg', None) -Unparsed entity decl: - (u'unparsed_entity', None, u'entity.file', None, u'notation') -Start element: - u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'} -NS decl: - u'myns' u'http://www.python.org/namespace' -Start element: - u'http://www.python.org/namespace!subelement' {} -Character data: - u'Contents of subelements' -End element: - u'http://www.python.org/namespace!subelement' -End of NS decl: - u'myns' -Start element: - u'sub2' {} -Start of CDATA section -Character data: - u'contents of CDATA section' -End of CDATA section -End element: - u'sub2' -External entity ref: (None, u'entity.file', None) -End element: - u'root' - -Testing constructor for proper handling of namespace_separator values: -Legal values tested o.k. -Caught expected TypeError: -ParserCreate() argument 2 must be string or None, not int -Caught expected ValueError: -namespace_separator must be at most one character, omitted, or None Deleted: /python/branches/p3yk/Lib/test/output/test_threadedtempfile ============================================================================== --- /python/branches/p3yk/Lib/test/output/test_threadedtempfile Fri Apr 27 21:54:29 2007 +++ (empty file) @@ -1,5 +0,0 @@ -test_threadedtempfile -Creating -Starting -Reaping -Done: errors 0 ok 1000 Deleted: /python/branches/p3yk/Lib/test/output/xmltests ============================================================================== --- /python/branches/p3yk/Lib/test/output/xmltests Fri Apr 27 21:54:29 2007 +++ (empty file) @@ -1,364 +0,0 @@ -xmltests -Passed testAAA -Passed setAttribute() sets ownerDocument -Passed setAttribute() sets ownerElement -Test Succeeded testAAA -Passed assertion: len(Node.allnodes) == 0 -Passed testAAB -Test Succeeded testAAB -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Passed Test -Passed Test -Passed Test -Passed Test -Passed Test -Passed Test -Test Succeeded testAddAttr -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Test Succeeded testAppendChild -Passed assertion: len(Node.allnodes) == 0 -Passed appendChild() -Test Succeeded testAppendChildFragment -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testAttrListItem -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testAttrListItemNS -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testAttrListItems -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testAttrListKeys -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testAttrListKeysNS -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testAttrListLength -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testAttrListValues -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testAttrList__getitem__ -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testAttrList__setitem__ -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Test Succeeded testAttributeRepr -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Passed Test -Passed Test -Passed Test -Test Succeeded testChangeAttr -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testChildNodes -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testCloneAttributeDeep -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testCloneAttributeShallow -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testCloneDocumentDeep -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testCloneDocumentShallow -Passed assertion: len(Node.allnodes) == 0 -Passed clone of element has same attribute keys -Passed clone of attribute node has proper attribute values -Passed clone of attribute node correctly owned -Passed testCloneElementDeep -Test Succeeded testCloneElementDeep -Passed assertion: len(Node.allnodes) == 0 -Passed clone of element has same attribute keys -Passed clone of attribute node has proper attribute values -Passed clone of attribute node correctly owned -Passed testCloneElementShallow -Test Succeeded testCloneElementShallow -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testClonePIDeep -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testClonePIShallow -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testComment -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testCreateAttributeNS -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testCreateElementNS -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Passed Test -Test Succeeded testDeleteAttr -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testDocumentElement -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Test Succeeded testElement -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Test Succeeded testElementReprAndStr -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testFirstChild -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testGetAttrLength -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testGetAttrList -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testGetAttrValues -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testGetAttribute -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testGetAttributeNS -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testGetAttributeNode -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Test Succeeded testGetElementsByTagName -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Test Succeeded testGetElementsByTagNameNS -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testGetEmptyNodeListFromElementsByTagNameNS -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testHasChildNodes -Passed assertion: len(Node.allnodes) == 0 -Passed testInsertBefore -- node properly placed in tree -Passed testInsertBefore -- node properly placed in tree -Passed testInsertBefore -- node properly placed in tree -Test Succeeded testInsertBefore -Passed assertion: len(Node.allnodes) == 0 -Passed insertBefore(, None) -Passed insertBefore(, orig) -Test Succeeded testInsertBeforeFragment -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testLegalChildren -Passed assertion: len(Node.allnodes) == 0 -Passed NamedNodeMap.__setitem__() sets ownerDocument -Passed NamedNodeMap.__setitem__() sets ownerElement -Passed NamedNodeMap.__setitem__() sets value -Passed NamedNodeMap.__setitem__() sets nodeValue -Test Succeeded testNamedNodeMapSetItem -Passed assertion: len(Node.allnodes) == 0 -Passed test NodeList.item() -Test Succeeded testNodeListItem -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Test Succeeded testNonZero -Passed assertion: len(Node.allnodes) == 0 -Passed testNormalize -- preparation -Passed testNormalize -- result -Passed testNormalize -- single empty node removed -Test Succeeded testNormalize -Passed assertion: len(Node.allnodes) == 0 -Passed testParents -Test Succeeded testParents -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testParse -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testParseAttributeNamespaces -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testParseAttributes -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testParseElement -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testParseElementNamespaces -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Test Succeeded testParseFromFile -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testParseProcessingInstructions -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testParseString -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testProcessingInstruction -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testProcessingInstructionRepr -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Test Succeeded testRemoveAttr -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Test Succeeded testRemoveAttrNS -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Test Succeeded testRemoveAttributeNode -Passed assertion: len(Node.allnodes) == 0 -Passed replaceChild() -Test Succeeded testReplaceChildFragment -Passed assertion: len(Node.allnodes) == 0 -Passed testSAX2DOM - siblings -Passed testSAX2DOM - parents -Test Succeeded testSAX2DOM -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testSetAttrValueandNodeValue -Passed assertion: len(Node.allnodes) == 0 -Passed testSiblings -Test Succeeded testSiblings -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testTextNodeRepr -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testTextRepr -Passed assertion: len(Node.allnodes) == 0 -Caught expected exception when adding extra document element. -Test Succeeded testTooManyDocumentElements -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testUnlink -Passed assertion: len(Node.allnodes) == 0 -Test Succeeded testWriteText -Passed assertion: len(Node.allnodes) == 0 -Passed Test -Passed Test -Test Succeeded testWriteXML -Passed assertion: len(Node.allnodes) == 0 -All tests succeeded -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -OK. -PI: - 'xml-stylesheet' 'href="stylesheet.css"' -Comment: - ' comment data ' -Notation declared: ('notation', None, 'notation.jpeg', None) -Unparsed entity decl: - ('unparsed_entity', None, 'entity.file', None, 'notation') -Start element: - 'root' {'attr1': 'value1', 'attr2': 'value2\xe1\xbd\x80'} -NS decl: - 'myns' 'http://www.python.org/namespace' -Start element: - 'http://www.python.org/namespace!subelement' {} -Character data: - 'Contents of subelements' -End element: - 'http://www.python.org/namespace!subelement' -End of NS decl: - 'myns' -Start element: - 'sub2' {} -Start of CDATA section -Character data: - 'contents of CDATA section' -End of CDATA section -End element: - 'sub2' -External entity ref: (None, 'entity.file', None) -End element: - 'root' -PI: - u'xml-stylesheet' u'href="stylesheet.css"' -Comment: - u' comment data ' -Notation declared: (u'notation', None, u'notation.jpeg', None) -Unparsed entity decl: - (u'unparsed_entity', None, u'entity.file', None, u'notation') -Start element: - u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'} -NS decl: - u'myns' u'http://www.python.org/namespace' -Start element: - u'http://www.python.org/namespace!subelement' {} -Character data: - u'Contents of subelements' -End element: - u'http://www.python.org/namespace!subelement' -End of NS decl: - u'myns' -Start element: - u'sub2' {} -Start of CDATA section -Character data: - u'contents of CDATA section' -End of CDATA section -End element: - u'sub2' -External entity ref: (None, u'entity.file', None) -End element: - u'root' -PI: - u'xml-stylesheet' u'href="stylesheet.css"' -Comment: - u' comment data ' -Notation declared: (u'notation', None, u'notation.jpeg', None) -Unparsed entity decl: - (u'unparsed_entity', None, u'entity.file', None, u'notation') -Start element: - u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'} -NS decl: - u'myns' u'http://www.python.org/namespace' -Start element: - u'http://www.python.org/namespace!subelement' {} -Character data: - u'Contents of subelements' -End element: - u'http://www.python.org/namespace!subelement' -End of NS decl: - u'myns' -Start element: - u'sub2' {} -Start of CDATA section -Character data: - u'contents of CDATA section' -End of CDATA section -End element: - u'sub2' -External entity ref: (None, u'entity.file', None) -End element: - u'root' - -Testing constructor for proper handling of namespace_separator values: -Legal values tested o.k. -Caught expected TypeError: -ParserCreate() argument 2 must be string or None, not int -Caught expected ValueError: -namespace_separator must be at most one character, omitted, or None -Passed test_attrs_empty -Passed test_attrs_wattr -Passed test_double_quoteattr -Passed test_escape_all -Passed test_escape_basic -Passed test_escape_extra -Passed test_expat_attrs_empty -Passed test_expat_attrs_wattr -Passed test_expat_dtdhandler -Passed test_expat_entityresolver -Passed test_expat_file -Passed test_expat_incomplete -Passed test_expat_incremental -Passed test_expat_incremental_reset -Passed test_expat_inpsource_filename -Passed test_expat_inpsource_location -Passed test_expat_inpsource_stream -Passed test_expat_inpsource_sysid -Passed test_expat_locator_noinfo -Passed test_expat_locator_withinfo -Passed test_expat_nsattrs_empty -Passed test_expat_nsattrs_wattr -Passed test_filter_basic -Passed test_make_parser -Passed test_make_parser2 -Passed test_nsattrs_empty -Passed test_nsattrs_wattr -Passed test_quoteattr_basic -Passed test_single_double_quoteattr -Passed test_single_quoteattr -Passed test_xmlgen_attr_escape -Passed test_xmlgen_basic -Passed test_xmlgen_content -Passed test_xmlgen_content_escape -Passed test_xmlgen_ignorable -Passed test_xmlgen_ns -Passed test_xmlgen_pi -37 tests, 0 failures Modified: python/branches/p3yk/Lib/test/outstanding_bugs.py ============================================================================== --- python/branches/p3yk/Lib/test/outstanding_bugs.py (original) +++ python/branches/p3yk/Lib/test/outstanding_bugs.py Fri Apr 27 21:54:29 2007 @@ -10,13 +10,44 @@ from test import test_support # -# No test cases for outstanding bugs at the moment. +# One test case for outstanding bugs at the moment: # +class TestDifflibLongestMatch(unittest.TestCase): + # From Patch #1678339: + # The find_longest_match method in the difflib's SequenceMatcher has a bug. + + # The bug is in turn caused by a problem with creating a b2j mapping which + # should contain a list of indices for each of the list elements in b. + # However, when the b2j mapping is being created (this is being done in + # __chain_b method in the SequenceMatcher) the mapping becomes broken. The + # cause of this is that for the frequently used elements the list of indices + # is removed and the element is being enlisted in the populardict mapping. + + # The test case tries to match two strings like: + # abbbbbb.... and ...bbbbbbc + + # The number of b is equal and the find_longest_match should have returned + # the proper amount. However, in case the number of "b"s is large enough, the + # method reports that the length of the longest common substring is 0. It + # simply can't find it. + + # A bug was raised some time ago on this matter. It's ID is 1528074. + + def test_find_longest_match(self): + import difflib + for i in (190, 200, 210): + text1 = "a" + "b"*i + text2 = "b"*i + "c" + m = difflib.SequenceMatcher(None, text1, text2) + (aptr, bptr, l) = m.find_longest_match(0, len(text1), 0, len(text2)) + self.assertEquals(i, l) + self.assertEquals(aptr, 1) + self.assertEquals(bptr, 0) + def test_main(): - #test_support.run_unittest() - pass + test_support.run_unittest(TestDifflibLongestMatch) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/pickletester.py ============================================================================== --- python/branches/p3yk/Lib/test/pickletester.py (original) +++ python/branches/p3yk/Lib/test/pickletester.py Fri Apr 27 21:54:29 2007 @@ -835,6 +835,24 @@ y = self.loads(s) self.assertEqual(y._proto, None) + def test_reduce_ex_calls_base(self): + for proto in 0, 1, 2: + x = REX_four() + self.assertEqual(x._proto, None) + s = self.dumps(x, proto) + self.assertEqual(x._proto, proto) + y = self.loads(s) + self.assertEqual(y._proto, proto) + + def test_reduce_calls_base(self): + for proto in 0, 1, 2: + x = REX_five() + self.assertEqual(x._reduce_called, 0) + s = self.dumps(x, proto) + self.assertEqual(x._reduce_called, 1) + y = self.loads(s) + self.assertEqual(y._reduce_called, 1) + # Test classes for reduce_ex class REX_one(object): @@ -859,6 +877,20 @@ def __reduce__(self): raise TestFailed, "This __reduce__ shouldn't be called" +class REX_four(object): + _proto = None + def __reduce_ex__(self, proto): + self._proto = proto + return object.__reduce_ex__(self, proto) + # Calling base class method should succeed + +class REX_five(object): + _reduce_called = 0 + def __reduce__(self): + self._reduce_called = 1 + return object.__reduce__(self) + # This one used to fail with infinite recursion + # Test classes for newobj class MyInt(int): Modified: python/branches/p3yk/Lib/test/regrtest.py ============================================================================== --- python/branches/p3yk/Lib/test/regrtest.py (original) +++ python/branches/p3yk/Lib/test/regrtest.py Fri Apr 27 21:54:29 2007 @@ -474,7 +474,7 @@ STDTESTS = [ 'test_grammar', 'test_opcodes', - 'test_operations', + 'test_dict', 'test_builtin', 'test_exceptions', 'test_types', 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 Fri Apr 27 21:54:29 2007 @@ -1104,6 +1104,9 @@ self.checkequal('Abc', 'abc', 'translate', table) self.checkequal('xyz', 'xyz', 'translate', table) self.checkequal('yz', 'xyz', 'translate', table, 'x') + self.checkequal('yx', 'zyzzx', 'translate', None, 'z') + self.checkequal('zyzzx', 'zyzzx', 'translate', None, '') + self.checkequal('zyzzx', 'zyzzx', 'translate', None) self.checkraises(ValueError, 'xyz', 'translate', 'too short', 'strip') self.checkraises(ValueError, 'xyz', 'translate', 'too short') 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 Fri Apr 27 21:54:29 2007 @@ -1,7 +1,5 @@ import unittest -from test import test_support - -from test.test_support import verify, verbose +from test.test_support import verbose, run_unittest import sys import warnings @@ -20,15 +18,15 @@ # Silent fail here seems the best route since some modules # may not be available in all environments. return - verify(hasattr(sys.modules[modname], "__all__"), - "%s has no __all__ attribute" % modname) + self.failUnless(hasattr(sys.modules[modname], "__all__"), + "%s has no __all__ attribute" % modname) names = {} exec("from %s import *" % modname, names) if "__builtins__" in names: del names["__builtins__"] keys = set(names) all = set(sys.modules[modname].__all__) - verify(keys==all, "%s != %s" % (keys, all)) + self.assertEqual(keys, all) def test_all(self): if not sys.platform.startswith('java'): @@ -177,7 +175,7 @@ def test_main(): - test_support.run_unittest(AllTest) + run_unittest(AllTest) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_array.py ============================================================================== --- python/branches/p3yk/Lib/test/test_array.py (original) +++ python/branches/p3yk/Lib/test/test_array.py Fri Apr 27 21:54:29 2007 @@ -111,6 +111,21 @@ self.assertEqual(a.x, b.x) self.assertEqual(type(a), type(b)) + def test_pickle_for_empty_array(self): + for protocol in (0, 1, 2): + a = array.array(self.typecode) + b = loads(dumps(a, protocol)) + self.assertNotEqual(id(a), id(b)) + self.assertEqual(a, b) + + a = ArraySubclass(self.typecode) + a.x = 10 + b = loads(dumps(a, protocol)) + self.assertNotEqual(id(a), id(b)) + self.assertEqual(a, b) + self.assertEqual(a.x, b.x) + self.assertEqual(type(a), type(b)) + def test_insert(self): a = array.array(self.typecode, self.example) a.insert(0, self.example[0]) @@ -713,7 +728,6 @@ return array.array.__new__(cls, 'c', s) def __init__(self, s, color='blue'): - array.array.__init__(self, 'c', s) self.color = color def strip(self): 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 Fri Apr 27 21:54:29 2007 @@ -28,7 +28,7 @@ self.stream = StringIO.StringIO() sys.stdout = sys.stderr = self.stream atexit._clear() - + def tearDown(self): sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ @@ -50,63 +50,63 @@ 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 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): + + 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) Modified: python/branches/p3yk/Lib/test/test_base64.py ============================================================================== --- python/branches/p3yk/Lib/test/test_base64.py (original) +++ python/branches/p3yk/Lib/test/test_base64.py Fri Apr 27 21:54:29 2007 @@ -183,16 +183,8 @@ -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(LegacyBase64TestCase)) - suite.addTest(unittest.makeSuite(BaseXYTestCase)) - return suite - - def test_main(): - test_support.run_suite(suite()) - + test_support.run_unittest(__name__) if __name__ == '__main__': - unittest.main(defaultTest='suite') + test_main() Modified: python/branches/p3yk/Lib/test/test_binascii.py ============================================================================== --- python/branches/p3yk/Lib/test/test_binascii.py (original) +++ python/branches/p3yk/Lib/test/test_binascii.py Fri Apr 27 21:54:29 2007 @@ -148,6 +148,15 @@ "0"*75+"=\r\n=FF\r\n=FF\r\n=FF" ) + self.assertEqual(binascii.b2a_qp('\0\n'), '=00\n') + self.assertEqual(binascii.b2a_qp('\0\n', quotetabs=True), '=00\n') + self.assertEqual(binascii.b2a_qp('foo\tbar\t\n'), 'foo\tbar=09\n') + self.assertEqual(binascii.b2a_qp('foo\tbar\t\n', quotetabs=True), 'foo=09bar=09\n') + + self.assertEqual(binascii.b2a_qp('.'), '=2E') + self.assertEqual(binascii.b2a_qp('.\n'), '=2E\n') + self.assertEqual(binascii.b2a_qp('a.\n'), 'a.\n') + def test_empty_string(self): # A test for SF bug #1022953. Make sure SystemError is not raised. for n in ['b2a_qp', 'a2b_hex', 'b2a_base64', 'a2b_uu', 'a2b_qp', 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 Fri Apr 27 21:54:29 2007 @@ -321,7 +321,7 @@ self.assertEqual(pickle.dumps(False), "I00\n.") self.assertEqual(pickle.dumps(True, True), "I01\n.") self.assertEqual(pickle.dumps(False, True), "I00\n.") - + try: import cPickle except ImportError: Modified: python/branches/p3yk/Lib/test/test_bsddb3.py ============================================================================== --- python/branches/p3yk/Lib/test/test_bsddb3.py (original) +++ python/branches/p3yk/Lib/test/test_bsddb3.py Fri Apr 27 21:54:29 2007 @@ -4,7 +4,7 @@ """ import sys import unittest -from test.test_support import requires, verbose, run_suite, unlink +from test.test_support import requires, verbose, run_unittest, unlink # When running as a script instead of within the regrtest framework, skip the # requires test, since it's obvious we want to run them. @@ -58,9 +58,7 @@ # For invocation through regrtest def test_main(): - tests = suite() - run_suite(tests) - + run_unittest(suite()) # For invocation as a script if __name__ == '__main__': @@ -73,4 +71,4 @@ print('python version: %s' % sys.version) print('-=' * 38) - unittest.main(defaultTest='suite') + test_main() 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 Fri Apr 27 21:54:29 2007 @@ -107,9 +107,12 @@ __import__('sys') __import__('time') __import__('string') + __import__(name='sys') + __import__(name='time', level=0) self.assertRaises(ImportError, __import__, 'spamspam') self.assertRaises(TypeError, __import__, 1, 2, 3, 4) self.assertRaises(ValueError, __import__, '') + self.assertRaises(TypeError, __import__, 'sys', name='sys') def test_abs(self): # int @@ -207,15 +210,21 @@ compile('print(1)\n', '', 'exec') bom = '\xef\xbb\xbf' compile(bom + 'print(1)\n', '', 'exec') + compile(source='pass', filename='?', mode='exec') + compile(dont_inherit=0, filename='tmp', source='0', mode='eval') + compile('pass', '?', dont_inherit=1, mode='exec') self.assertRaises(TypeError, compile) self.assertRaises(ValueError, compile, 'print(42)\n', '', 'badmode') self.assertRaises(ValueError, compile, 'print(42)\n', '', 'single', 0xff) self.assertRaises(TypeError, compile, chr(0), 'f', 'exec') + self.assertRaises(TypeError, compile, 'pass', '?', 'exec', + mode='eval', source='0', filename='tmp') if have_unicode: compile(unicode('print(u"\xc3\xa5")\n', 'utf8'), '', 'exec') self.assertRaises(TypeError, compile, unichr(0), 'f', 'exec') self.assertRaises(ValueError, compile, unicode('a = 1'), 'f', 'bad') + def test_delattr(self): import sys sys.spam = 1 @@ -1035,6 +1044,11 @@ self.assertRaises(ValueError, int, '53', 40) self.assertRaises(TypeError, int, 1, 12) + # SF patch #1638879: embedded NULs were not detected with + # explicit base + self.assertRaises(ValueError, int, '123\0', 10) + self.assertRaises(ValueError, int, '123\x00 245', 20) + self.assertEqual(int('100000000000000000000000000000000', 2), 4294967296) self.assertEqual(int('102002022201221111211', 3), 4294967296) @@ -1138,10 +1152,10 @@ self.assertEqual(int(Foo0()), 42) self.assertEqual(int(Foo1()), 42) - # XXX invokes __int__ now + # XXX invokes __int__ now # self.assertEqual(long(Foo2()), 42L) self.assertEqual(int(Foo3()), 0) - # XXX likewise + # XXX likewise # self.assertEqual(long(Foo4()), 42) # self.assertRaises(TypeError, long, Foo5()) Modified: python/branches/p3yk/Lib/test/test_cfgparser.py ============================================================================== --- python/branches/p3yk/Lib/test/test_cfgparser.py (original) +++ python/branches/p3yk/Lib/test/test_cfgparser.py Fri Apr 27 21:54:29 2007 @@ -417,6 +417,18 @@ self.assertEqual(cf.get("section", "ok"), "xxx/%s") self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s") + def test_set_malformatted_interpolation(self): + cf = self.fromstring("[sect]\n" + "option1=foo\n") + + self.assertEqual(cf.get('sect', "option1"), "foo") + + self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo") + self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%") + self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo") + + self.assertEqual(cf.get('sect', "option1"), "foo") + def test_set_nonstring_types(self): cf = self.fromstring("[sect]\n" "option1=foo\n") Modified: python/branches/p3yk/Lib/test/test_cmath.py ============================================================================== --- python/branches/p3yk/Lib/test/test_cmath.py (original) +++ python/branches/p3yk/Lib/test/test_cmath.py Fri Apr 27 21:54:29 2007 @@ -1,52 +1,196 @@ -#! /usr/bin/env python -""" Simple test script for cmathmodule.c - Roger E. Masse -""" +from test.test_support import run_unittest +import unittest import cmath, math -from test.test_support import verbose, verify, TestFailed -verify(abs(cmath.log(10) - math.log(10)) < 1e-9) -verify(abs(cmath.log(10,2) - math.log(10,2)) < 1e-9) -try: - cmath.log('a') -except TypeError: - pass -else: - raise TestFailed - -try: - cmath.log(10, 'a') -except TypeError: - pass -else: - raise TestFailed - - -testdict = {'acos' : 1.0, - 'acosh' : 1.0, - 'asin' : 1.0, - 'asinh' : 1.0, - 'atan' : 0.2, - 'atanh' : 0.2, - 'cos' : 1.0, - 'cosh' : 1.0, - 'exp' : 1.0, - 'log' : 1.0, - 'log10' : 1.0, - 'sin' : 1.0, - 'sinh' : 1.0, - 'sqrt' : 1.0, - 'tan' : 1.0, - 'tanh' : 1.0} - -for func in testdict.keys(): - f = getattr(cmath, func) - r = f(testdict[func]) - if verbose: - print('Calling %s(%f) = %f' % (func, testdict[func], abs(r))) - -p = cmath.pi -e = cmath.e -if verbose: - print('PI = ', abs(p)) - print('E = ', abs(e)) +class CMathTests(unittest.TestCase): + # list of all functions in cmath + test_functions = [getattr(cmath, fname) for fname in [ + 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', + 'cos', 'cosh', 'exp', 'log', 'log10', 'sin', 'sinh', + 'sqrt', 'tan', 'tanh']] + # test first and second arguments independently for 2-argument log + test_functions.append(lambda x : cmath.log(x, 1729. + 0j)) + test_functions.append(lambda x : cmath.log(14.-27j, x)) + + def cAssertAlmostEqual(self, a, b, rel_eps = 1e-10, abs_eps = 1e-100): + """Check that two complex numbers are almost equal.""" + # the two complex numbers are considered almost equal if + # either the relative error is <= rel_eps or the absolute error + # is tiny, <= abs_eps. + if a == b == 0: + return + absolute_error = abs(a-b) + relative_error = absolute_error/max(abs(a), abs(b)) + if relative_error > rel_eps and absolute_error > abs_eps: + self.fail("%s and %s are not almost equal" % (a, b)) + + def test_constants(self): + e_expected = 2.71828182845904523536 + pi_expected = 3.14159265358979323846 + self.assertAlmostEqual(cmath.pi, pi_expected, 9, + "cmath.pi is %s; should be %s" % (cmath.pi, pi_expected)) + self.assertAlmostEqual(cmath.e, e_expected, 9, + "cmath.e is %s; should be %s" % (cmath.e, e_expected)) + + def test_user_object(self): + # Test automatic calling of __complex__ and __float__ by cmath + # functions + + # some random values to use as test values; we avoid values + # for which any of the functions in cmath is undefined + # (i.e. 0., 1., -1., 1j, -1j) or would cause overflow + cx_arg = 4.419414439 + 1.497100113j + flt_arg = -6.131677725 + + # a variety of non-complex numbers, used to check that + # non-complex return values from __complex__ give an error + non_complexes = ["not complex", 1, 5, 2., None, + object(), NotImplemented] + + # Now we introduce a variety of classes whose instances might + # end up being passed to the cmath functions + + # usual case: new-style class implementing __complex__ + class MyComplex(object): + def __init__(self, value): + self.value = value + def __complex__(self): + return self.value + + # old-style class implementing __complex__ + class MyComplexOS: + def __init__(self, value): + self.value = value + def __complex__(self): + return self.value + + # classes for which __complex__ raises an exception + class SomeException(Exception): + pass + class MyComplexException(object): + def __complex__(self): + raise SomeException + class MyComplexExceptionOS: + def __complex__(self): + raise SomeException + + # some classes not providing __float__ or __complex__ + class NeitherComplexNorFloat(object): + pass + class NeitherComplexNorFloatOS: + pass + class MyInt(object): + def __int__(self): return 2 + def __long__(self): return 2 + def __index__(self): return 2 + class MyIntOS: + def __int__(self): return 2 + def __long__(self): return 2 + def __index__(self): return 2 + + # other possible combinations of __float__ and __complex__ + # that should work + class FloatAndComplex(object): + def __float__(self): + return flt_arg + def __complex__(self): + return cx_arg + class FloatAndComplexOS: + def __float__(self): + return flt_arg + def __complex__(self): + return cx_arg + class JustFloat(object): + def __float__(self): + return flt_arg + class JustFloatOS: + def __float__(self): + return flt_arg + + for f in self.test_functions: + # usual usage + self.cAssertAlmostEqual(f(MyComplex(cx_arg)), f(cx_arg)) + self.cAssertAlmostEqual(f(MyComplexOS(cx_arg)), f(cx_arg)) + # other combinations of __float__ and __complex__ + self.cAssertAlmostEqual(f(FloatAndComplex()), f(cx_arg)) + self.cAssertAlmostEqual(f(FloatAndComplexOS()), f(cx_arg)) + self.cAssertAlmostEqual(f(JustFloat()), f(flt_arg)) + self.cAssertAlmostEqual(f(JustFloatOS()), f(flt_arg)) + # TypeError should be raised for classes not providing + # either __complex__ or __float__, even if they provide + # __int__, __long__ or __index__. An old-style class + # currently raises AttributeError instead of a TypeError; + # this could be considered a bug. + self.assertRaises(TypeError, f, NeitherComplexNorFloat()) + self.assertRaises(TypeError, f, MyInt()) + self.assertRaises(Exception, f, NeitherComplexNorFloatOS()) + self.assertRaises(Exception, f, MyIntOS()) + # non-complex return value from __complex__ -> TypeError + for bad_complex in non_complexes: + self.assertRaises(TypeError, f, MyComplex(bad_complex)) + self.assertRaises(TypeError, f, MyComplexOS(bad_complex)) + # exceptions in __complex__ should be propagated correctly + self.assertRaises(SomeException, f, MyComplexException()) + self.assertRaises(SomeException, f, MyComplexExceptionOS()) + + def test_input_type(self): + # ints and longs should be acceptable inputs to all cmath + # functions, by virtue of providing a __float__ method + for f in self.test_functions: + for arg in [2, 2.]: + self.cAssertAlmostEqual(f(arg), f(arg.__float__())) + + # but strings should give a TypeError + for f in self.test_functions: + for arg in ["a", "long_string", "0", "1j", ""]: + self.assertRaises(TypeError, f, arg) + + def test_cmath_matches_math(self): + # check that corresponding cmath and math functions are equal + # for floats in the appropriate range + + # test_values in (0, 1) + test_values = [0.01, 0.1, 0.2, 0.5, 0.9, 0.99] + + # test_values for functions defined on [-1., 1.] + unit_interval = test_values + [-x for x in test_values] + \ + [0., 1., -1.] + + # test_values for log, log10, sqrt + positive = test_values + [1.] + [1./x for x in test_values] + nonnegative = [0.] + positive + + # test_values for functions defined on the whole real line + real_line = [0.] + positive + [-x for x in positive] + + test_functions = { + 'acos' : unit_interval, + 'asin' : unit_interval, + 'atan' : real_line, + 'cos' : real_line, + 'cosh' : real_line, + 'exp' : real_line, + 'log' : positive, + 'log10' : positive, + 'sin' : real_line, + 'sinh' : real_line, + 'sqrt' : nonnegative, + 'tan' : real_line, + 'tanh' : real_line} + + for fn, values in test_functions.items(): + float_fn = getattr(math, fn) + complex_fn = getattr(cmath, fn) + for v in values: + self.cAssertAlmostEqual(float_fn(v), complex_fn(v)) + + # test two-argument version of log with various bases + for base in [0.5, 2., 10.]: + for v in positive: + self.cAssertAlmostEqual(cmath.log(v, base), math.log(v, base)) + +def test_main(): + run_unittest(CMathTests) + +if __name__ == "__main__": + test_main() Modified: python/branches/p3yk/Lib/test/test_cmd_line.py ============================================================================== --- python/branches/p3yk/Lib/test/test_cmd_line.py (original) +++ python/branches/p3yk/Lib/test/test_cmd_line.py Fri Apr 27 21:54:29 2007 @@ -6,7 +6,7 @@ class CmdLineTest(unittest.TestCase): def start_python(self, cmd_line): - outfp, infp = popen2.popen4('%s %s' % (sys.executable, cmd_line)) + outfp, infp = popen2.popen4('"%s" %s' % (sys.executable, cmd_line)) infp.close() data = outfp.read() outfp.close() Modified: python/branches/p3yk/Lib/test/test_codecencodings_cn.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecencodings_cn.py (original) +++ python/branches/p3yk/Lib/test/test_codecencodings_cn.py Fri Apr 27 21:54:29 2007 @@ -51,11 +51,7 @@ has_iso10646 = True def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_GB2312)) - suite.addTest(unittest.makeSuite(Test_GBK)) - suite.addTest(unittest.makeSuite(Test_GB18030)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_codecencodings_hk.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecencodings_hk.py (original) +++ python/branches/p3yk/Lib/test/test_codecencodings_hk.py Fri Apr 27 21:54:29 2007 @@ -21,9 +21,7 @@ ) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_Big5HKSCS)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_codecencodings_jp.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecencodings_jp.py (original) +++ python/branches/p3yk/Lib/test/test_codecencodings_jp.py Fri Apr 27 21:54:29 2007 @@ -99,13 +99,7 @@ ) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_CP932)) - suite.addTest(unittest.makeSuite(Test_EUC_JISX0213)) - suite.addTest(unittest.makeSuite(Test_EUC_JP_COMPAT)) - suite.addTest(unittest.makeSuite(Test_SJIS_COMPAT)) - suite.addTest(unittest.makeSuite(Test_SJISX0213)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_codecencodings_kr.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecencodings_kr.py (original) +++ python/branches/p3yk/Lib/test/test_codecencodings_kr.py Fri Apr 27 21:54:29 2007 @@ -45,11 +45,7 @@ ) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_CP949)) - suite.addTest(unittest.makeSuite(Test_EUCKR)) - suite.addTest(unittest.makeSuite(Test_JOHAB)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_codecencodings_tw.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecencodings_tw.py (original) +++ python/branches/p3yk/Lib/test/test_codecencodings_tw.py Fri Apr 27 21:54:29 2007 @@ -21,9 +21,7 @@ ) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_Big5)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_codecmaps_cn.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecmaps_cn.py (original) +++ python/branches/p3yk/Lib/test/test_codecmaps_cn.py Fri Apr 27 21:54:29 2007 @@ -20,10 +20,7 @@ 'MICSFT/WINDOWS/CP936.TXT' def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestGB2312Map)) - suite.addTest(unittest.makeSuite(TestGBKMap)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_codecmaps_hk.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecmaps_hk.py (original) +++ python/branches/p3yk/Lib/test/test_codecmaps_hk.py Fri Apr 27 21:54:29 2007 @@ -14,9 +14,7 @@ mapfileurl = 'http://people.freebsd.org/~perky/i18n/BIG5HKSCS.TXT' def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestBig5HKSCSMap)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_codecmaps_jp.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecmaps_jp.py (original) +++ python/branches/p3yk/Lib/test/test_codecmaps_jp.py Fri Apr 27 21:54:29 2007 @@ -61,13 +61,7 @@ def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestCP932Map)) - suite.addTest(unittest.makeSuite(TestEUCJPCOMPATMap)) - suite.addTest(unittest.makeSuite(TestSJISCOMPATMap)) - suite.addTest(unittest.makeSuite(TestEUCJISX0213Map)) - suite.addTest(unittest.makeSuite(TestSJISX0213Map)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_codecmaps_kr.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecmaps_kr.py (original) +++ python/branches/p3yk/Lib/test/test_codecmaps_kr.py Fri Apr 27 21:54:29 2007 @@ -34,11 +34,7 @@ pass_dectest = [('\\', u'\u20a9')] def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestCP949Map)) - suite.addTest(unittest.makeSuite(TestEUCKRMap)) - suite.addTest(unittest.makeSuite(TestJOHABMap)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_codecmaps_tw.py ============================================================================== --- python/branches/p3yk/Lib/test/test_codecmaps_tw.py (original) +++ python/branches/p3yk/Lib/test/test_codecmaps_tw.py Fri Apr 27 21:54:29 2007 @@ -25,10 +25,7 @@ ] def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestBIG5Map)) - suite.addTest(unittest.makeSuite(TestCP950Map)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_commands.py ============================================================================== --- python/branches/p3yk/Lib/test/test_commands.py (original) +++ python/branches/p3yk/Lib/test/test_commands.py Fri Apr 27 21:54:29 2007 @@ -4,6 +4,10 @@ ''' import unittest import os, tempfile, re +import warnings + +warnings.filterwarnings('ignore', r".*commands.getstatus.. is deprecated", + DeprecationWarning) from test.test_support import TestSkipped, run_unittest, reap_children from commands import * Modified: python/branches/p3yk/Lib/test/test_compile.py ============================================================================== --- python/branches/p3yk/Lib/test/test_compile.py (original) +++ python/branches/p3yk/Lib/test/test_compile.py Fri Apr 27 21:54:29 2007 @@ -399,13 +399,26 @@ # is the max. Ensure the result of too many annotations is a # SyntaxError. s = "def f((%s)): pass" - s %= ', '.join('a%d:%d' % (i,i) for i in xrange(65535)) + s %= ', '.join('a%d:%d' % (i,i) for i in xrange(65535)) self.assertRaises(SyntaxError, compile, s, '?', 'exec') # Test that the max # of annotations compiles. s = "def f((%s)): pass" s %= ', '.join('a%d:%d' % (i,i) for i in xrange(65534)) compile(s, '?', 'exec') - + + def test_mangling(self): + class A: + def f(): + __mangled = 1 + __not_mangled__ = 2 + import __mangled_mod + import __package__.module + + self.assert_("_A__mangled" in A.f.__code__.co_varnames) + self.assert_("__not_mangled__" in A.f.__code__.co_varnames) + self.assert_("_A__mangled_mod" in A.f.__code__.co_varnames) + self.assert_("__package__" in A.f.__code__.co_varnames) + def test_main(): test_support.run_unittest(TestSpecifics) 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 Fri Apr 27 21:54:29 2007 @@ -190,7 +190,7 @@ def testBytesLiteral(self): c = compiler.compile("b'foo'", '', 'eval') b = eval(c) - + c = compiler.compile('def f(b=b"foo"):\n' ' b[0] += 1\n' ' return b\n' @@ -200,7 +200,7 @@ dct = {} exec(c, dct) self.assertEquals(dct.get('result'), b"ioo") - + c = compiler.compile('def f():\n' ' b = b"foo"\n' ' b[0] += 1\n' Modified: python/branches/p3yk/Lib/test/test_complex.py ============================================================================== --- python/branches/p3yk/Lib/test/test_complex.py (original) +++ python/branches/p3yk/Lib/test/test_complex.py Fri Apr 27 21:54:29 2007 @@ -208,6 +208,8 @@ self.assertAlmostEqual(complex(), 0) self.assertAlmostEqual(complex("-1"), -1) self.assertAlmostEqual(complex("+1"), +1) + self.assertAlmostEqual(complex("(1+2j)"), 1+2j) + self.assertAlmostEqual(complex("(1.3+2.2j)"), 1.3+2.2j) class complex2(complex): pass self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j) @@ -237,12 +239,17 @@ self.assertRaises(ValueError, complex, "") self.assertRaises(TypeError, complex, None) self.assertRaises(ValueError, complex, "\0") + self.assertRaises(ValueError, complex, "3\09") self.assertRaises(TypeError, complex, "1", "2") self.assertRaises(TypeError, complex, "1", 42) self.assertRaises(TypeError, complex, 1, "2") self.assertRaises(ValueError, complex, "1+") self.assertRaises(ValueError, complex, "1+1j+1j") self.assertRaises(ValueError, complex, "--") + self.assertRaises(ValueError, complex, "(1+2j") + self.assertRaises(ValueError, complex, "1+2j)") + self.assertRaises(ValueError, complex, "1+(2j)") + self.assertRaises(ValueError, complex, "(1+2j)123") if test_support.have_unicode: self.assertRaises(ValueError, complex, unicode("1"*500)) self.assertRaises(ValueError, complex, unicode("x")) @@ -305,6 +312,11 @@ self.assertNotEqual(repr(-(1+0j)), '(-1+-0j)') + self.assertEqual(1-6j,complex(repr(1-6j))) + self.assertEqual(1+6j,complex(repr(1+6j))) + self.assertEqual(-6j,complex(repr(-6j))) + self.assertEqual(6j,complex(repr(6j))) + def test_neg(self): self.assertEqual(-(1+6j), -1-6j) Modified: python/branches/p3yk/Lib/test/test_contextlib.py ============================================================================== --- python/branches/p3yk/Lib/test/test_contextlib.py (original) +++ python/branches/p3yk/Lib/test/test_contextlib.py Fri Apr 27 21:54:29 2007 @@ -9,7 +9,7 @@ import unittest import threading from contextlib import * # Tests __all__ -from test.test_support import run_suite +from test import test_support class ContextManagerTestCase(unittest.TestCase): @@ -332,9 +332,7 @@ # This is needed to make the test actually run under regrtest.py! def test_main(): - run_suite( - unittest.defaultTestLoader.loadTestsFromModule(sys.modules[__name__]) - ) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_crypt.py ============================================================================== --- python/branches/p3yk/Lib/test/test_crypt.py (original) +++ python/branches/p3yk/Lib/test/test_crypt.py Fri Apr 27 21:54:29 2007 @@ -3,7 +3,7 @@ Roger E. Masse """ -from test.test_support import verify, verbose +from test.test_support import verbose import crypt c = crypt.crypt('mypassword', 'ab') 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 Fri Apr 27 21:54:29 2007 @@ -484,12 +484,16 @@ self.readerAssertEqual('a"b"c', [['a"b"c']]) def test_quotes_and_more(self): + # Excel would never write a field containing '"a"b', but when + # reading one, it will return 'ab'. self.readerAssertEqual('"a"b', [['ab']]) def test_lone_quote(self): self.readerAssertEqual('a"b', [['a"b']]) def test_quote_and_quote(self): + # Excel would never write a field containing '"a" "b"', but when + # reading one, it will return 'a "b"'. self.readerAssertEqual('"a" "b"', [['a "b"']]) def test_space_and_quote(self): Modified: python/branches/p3yk/Lib/test/test_ctypes.py ============================================================================== --- python/branches/p3yk/Lib/test/test_ctypes.py (original) +++ python/branches/p3yk/Lib/test/test_ctypes.py Fri Apr 27 21:54:29 2007 @@ -1,12 +1,12 @@ import unittest -from test.test_support import run_suite +from test.test_support import run_unittest import ctypes.test def test_main(): skipped, testcases = ctypes.test.get_tests(ctypes.test, "test_*.py", verbosity=0) suites = [unittest.makeSuite(t) for t in testcases] - run_suite(unittest.TestSuite(suites)) + run_unittest(unittest.TestSuite(suites)) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_curses.py ============================================================================== --- python/branches/p3yk/Lib/test/test_curses.py (original) +++ python/branches/p3yk/Lib/test/test_curses.py Fri Apr 27 21:54:29 2007 @@ -129,6 +129,12 @@ stdscr.touchline(5,5,0) stdscr.vline('a', 3) stdscr.vline('a', 3, curses.A_STANDOUT) + stdscr.chgat(5, 2, 3, curses.A_BLINK) + stdscr.chgat(3, curses.A_BOLD) + stdscr.chgat(5, 8, curses.A_UNDERLINE) + stdscr.chgat(curses.A_BLINK) + stdscr.refresh() + stdscr.vline(1,1, 'a', 3) stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT) @@ -241,12 +247,21 @@ except curses.panel.error: pass +def test_resize_term(stdscr): + if hasattr(curses, 'resizeterm'): + lines, cols = curses.LINES, curses.COLS + curses.resizeterm(lines - 1, cols + 1) + + if curses.LINES != lines - 1 or curses.COLS != cols + 1: + raise RuntimeError, "Expected resizeterm to update LINES and COLS" + def main(stdscr): curses.savetty() try: module_funcs(stdscr) window_funcs(stdscr) test_userptr_without_set(stdscr) + test_resize_term(stdscr) finally: curses.resetty() Modified: python/branches/p3yk/Lib/test/test_datetime.py ============================================================================== --- python/branches/p3yk/Lib/test/test_datetime.py (original) +++ python/branches/p3yk/Lib/test/test_datetime.py Fri Apr 27 21:54:29 2007 @@ -3,6 +3,7 @@ See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases """ +import os import sys import pickle import unittest @@ -135,7 +136,7 @@ # Base clase for testing a particular aspect of timedelta, time, date and # datetime comparisons. -class HarmlessMixedComparison(unittest.TestCase): +class HarmlessMixedComparison: # Test that __eq__ and __ne__ don't complain for mixed-type comparisons. # Subclasses must define 'theclass', and theclass(1, 1, 1) must be a @@ -174,7 +175,7 @@ ############################################################################# # timedelta tests -class TestTimeDelta(HarmlessMixedComparison): +class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase): theclass = timedelta @@ -521,7 +522,7 @@ class SubclassDate(date): sub_var = 1 -class TestDate(HarmlessMixedComparison): +class TestDate(HarmlessMixedComparison, unittest.TestCase): # Tests here should pass for both dates and datetimes, except for a # few tests that TestDateTime overrides. @@ -1452,6 +1453,21 @@ self.assertRaises(ValueError, self.theclass.utcfromtimestamp, insane) + def test_negative_float_fromtimestamp(self): + # Windows doesn't accept negative timestamps + if os.name == "nt": + return + # The result is tz-dependent; at least test that this doesn't + # fail (like it did before bug 1646728 was fixed). + self.theclass.fromtimestamp(-1.05) + + def test_negative_float_utcfromtimestamp(self): + # Windows doesn't accept negative timestamps + if os.name == "nt": + return + d = self.theclass.utcfromtimestamp(-1.05) + self.assertEquals(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000)) + def test_utcnow(self): import time @@ -1607,7 +1623,7 @@ class SubclassTime(time): sub_var = 1 -class TestTime(HarmlessMixedComparison): +class TestTime(HarmlessMixedComparison, unittest.TestCase): theclass = time @@ -1890,7 +1906,7 @@ # A mixin for classes with a tzinfo= argument. Subclasses must define # theclass as a class atribute, and theclass(1, 1, 1, tzinfo=whatever) # must be legit (which is true for time and datetime). -class TZInfoBase(unittest.TestCase): +class TZInfoBase: def test_argument_passing(self): cls = self.theclass @@ -2050,7 +2066,7 @@ # Testing time objects with a non-None tzinfo. -class TestTimeTZ(TestTime, TZInfoBase): +class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase): theclass = time def test_empty(self): @@ -2298,7 +2314,7 @@ # Testing datetime objects with a non-None tzinfo. -class TestDateTimeTZ(TestDateTime, TZInfoBase): +class TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase): theclass = datetime def test_trivial(self): @@ -3259,45 +3275,8 @@ self.assertEqual(as_datetime, datetime_sc) self.assertEqual(datetime_sc, as_datetime) -def test_suite(): - allsuites = [unittest.makeSuite(klass, 'test') - for klass in (TestModule, - TestTZInfo, - TestTimeDelta, - TestDateOnly, - TestDate, - TestDateTime, - TestTime, - TestTimeTZ, - TestDateTimeTZ, - TestTimezoneConversions, - Oddballs, - ) - ] - return unittest.TestSuite(allsuites) - def test_main(): - import gc - import sys - - thesuite = test_suite() - lastrc = None - while True: - test_support.run_suite(thesuite) - if 1: # change to 0, under a debug build, for some leak detection - break - gc.collect() - if gc.garbage: - raise SystemError("gc.garbage not empty after test run: %r" % - gc.garbage) - if hasattr(sys, 'gettotalrefcount'): - thisrc = sys.gettotalrefcount() - print('*' * 10, 'total refs:', thisrc, end=' ', file=sys.stderr) - if lastrc: - print('delta:', thisrc - lastrc, file=sys.stderr) - else: - print(file=sys.stderr) - lastrc = thisrc + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_defaultdict.py ============================================================================== --- python/branches/p3yk/Lib/test/test_defaultdict.py (original) +++ python/branches/p3yk/Lib/test/test_defaultdict.py Fri Apr 27 21:54:29 2007 @@ -132,6 +132,15 @@ self.assertEqual(d2.default_factory, list) self.assertEqual(d2, d1) + def test_keyerror_without_factory(self): + d1 = defaultdict() + try: + d1[(1,)] + except KeyError as err: + self.assertEqual(err.message, (1,)) + else: + self.fail("expected KeyError") + def test_main(): test_support.run_unittest(TestDefaultDict) Modified: python/branches/p3yk/Lib/test/test_deque.py ============================================================================== --- python/branches/p3yk/Lib/test/test_deque.py (original) +++ python/branches/p3yk/Lib/test/test_deque.py Fri Apr 27 21:54:29 2007 @@ -575,7 +575,7 @@ >>> for value in roundrobin('abc', 'd', 'efgh'): ... print(value) -... +... a d e 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 Fri Apr 27 21:54:29 2007 @@ -773,6 +773,22 @@ except TypeError: pass else: raise TestFailed, "calling object w/o call method should raise TypeError" + # Testing code to find most derived baseclass + class A(type): + def __new__(*args, **kwargs): + return type.__new__(*args, **kwargs) + + class B(object): + pass + + class C(object, metaclass=A): + pass + + # The most derived metaclass of D is A rather than type. + class D(B, C): + pass + + def pymods(): if verbose: print("Testing Python subclass of module...") log = [] @@ -1072,6 +1088,45 @@ raise TestFailed, "[''] slots not caught" class C(object): __slots__ = ["a", "a_b", "_a", "A0123456789Z"] + # XXX(nnorwitz): was there supposed to be something tested + # from the class above? + + # Test a single string is not expanded as a sequence. + class C(object): + __slots__ = "abc" + c = C() + c.abc = 5 + vereq(c.abc, 5) + + # Test unicode slot names + try: + unicode + except NameError: + pass + else: + # Test a single unicode string is not expanded as a sequence. + class C(object): + __slots__ = unicode("abc") + c = C() + c.abc = 5 + vereq(c.abc, 5) + + # _unicode_to_string used to modify slots in certain circumstances + slots = (unicode("foo"), unicode("bar")) + class C(object): + __slots__ = slots + x = C() + x.foo = 5 + vereq(x.foo, 5) + veris(type(slots[0]), unicode) + # this used to leak references + try: + class C(object): + __slots__ = [unichr(128)] + except (TypeError, UnicodeEncodeError): + pass + else: + raise TestFailed, "[unichr(128)] slots not caught" # Test leaks class Counted(object): @@ -1318,6 +1373,22 @@ else: verify(0, "__slots__ = [1] should be illegal") + class M1(type): + pass + class M2(type): + pass + class A1(object, metaclass=M1): + pass + class A2(object, metaclass=M2): + pass + try: + class B(A1, A2): + pass + except TypeError: + pass + else: + verify(0, "finding the most derived metaclass should have failed") + def classmethods(): if verbose: print("Testing class methods...") class C(object): @@ -2092,7 +2163,6 @@ __slots__ = ['prec'] def __init__(self, value=0.0, prec=12): self.prec = int(prec) - float.__init__(self, value) def __repr__(self): return "%.*g" % (self.prec, self) vereq(repr(precfloat(1.1)), "1.1") @@ -2644,6 +2714,51 @@ cant(o, type(1)) cant(o, type(None)) del o + class G(object): + __slots__ = ["a", "b"] + class H(object): + __slots__ = ["b", "a"] + try: + unicode + except NameError: + class I(object): + __slots__ = ["a", "b"] + else: + class I(object): + __slots__ = [unicode("a"), unicode("b")] + class J(object): + __slots__ = ["c", "b"] + class K(object): + __slots__ = ["a", "b", "d"] + class L(H): + __slots__ = ["e"] + class M(I): + __slots__ = ["e"] + class N(J): + __slots__ = ["__weakref__"] + class P(J): + __slots__ = ["__dict__"] + class Q(J): + pass + class R(J): + __slots__ = ["__dict__", "__weakref__"] + + for cls, cls2 in ((G, H), (G, I), (I, H), (Q, R), (R, Q)): + x = cls() + x.a = 1 + x.__class__ = cls2 + verify(x.__class__ is cls2, + "assigning %r as __class__ for %r silently failed" % (cls2, x)) + vereq(x.a, 1) + x.__class__ = cls + verify(x.__class__ is cls, + "assigning %r as __class__ for %r silently failed" % (cls, x)) + vereq(x.a, 1) + for cls in G, J, K, L, M, N, P, R, list, Int: + for cls2 in G, J, K, L, M, N, P, R, list, Int: + if cls is cls2: + continue + cant(cls(), cls2) def setdict(): if verbose: print("Testing __dict__ assignment...") @@ -3999,6 +4114,19 @@ check(iexpr, c, N1) check(iexpr, c, N2) +def test_assign_slice(): + # ceval.c's assign_slice used to check for + # tp->tp_as_sequence->sq_slice instead of + # tp->tp_as_sequence->sq_ass_slice + + class C(object): + def __setslice__(self, start, stop, value): + self.value = value + + c = C() + c[1:2] = 3 + vereq(c.value, 3) + def test_main(): weakref_segfault() # Must be first, somehow wrapper_segfault() @@ -4094,6 +4222,7 @@ test_init() methodwrapper() notimplemented() + test_assign_slice() if verbose: print("All OK") Modified: python/branches/p3yk/Lib/test/test_descrtut.py ============================================================================== --- python/branches/p3yk/Lib/test/test_descrtut.py (original) +++ python/branches/p3yk/Lib/test/test_descrtut.py Fri Apr 27 21:54:29 2007 @@ -243,7 +243,7 @@ static methods in C++ or Java. Here's an example: >>> class C: - ... + ... ... @staticmethod ... def foo(x, y): ... print("staticmethod", x, y) Modified: python/branches/p3yk/Lib/test/test_dict.py ============================================================================== --- python/branches/p3yk/Lib/test/test_dict.py (original) +++ python/branches/p3yk/Lib/test/test_dict.py Fri Apr 27 21:54:29 2007 @@ -425,7 +425,7 @@ except RuntimeError as err: self.assertEqual(err.args, (42,)) else: - self.fail_("e[42] didn't raise RuntimeError") + self.fail("e[42] didn't raise RuntimeError") class F(dict): def __init__(self): # An instance variable __missing__ should have no effect @@ -436,7 +436,7 @@ except KeyError as err: self.assertEqual(err.args, (42,)) else: - self.fail_("f[42] didn't raise KeyError") + self.fail("f[42] didn't raise KeyError") class G(dict): pass g = G() @@ -445,7 +445,7 @@ except KeyError as err: self.assertEqual(err.args, (42,)) else: - self.fail_("g[42] didn't raise KeyError") + self.fail("g[42] didn't raise KeyError") def test_tuple_keyerror(self): # SF #1576657 @@ -457,6 +457,76 @@ else: self.fail("missing KeyError") + def test_bad_key(self): + # Dictionary lookups should fail if __cmp__() raises an exception. + class CustomException(Exception): + pass + + class BadDictKey: + def __hash__(self): + return hash(self.__class__) + + def __eq__(self, other): + if isinstance(other, self.__class__): + raise CustomException + return other + + d = {} + x1 = BadDictKey() + x2 = BadDictKey() + d[x1] = 1 + for stmt in ['d[x2] = 2', + 'z = d[x2]', + 'x2 in d', + 'd.get(x2)', + 'd.setdefault(x2, 42)', + 'd.pop(x2)', + 'd.update({x2: 2})']: + try: + exec(stmt, locals()) + except CustomException: + pass + else: + self.fail("Statement %r didn't raise exception" % stmt) + + def test_resize1(self): + # Dict resizing bug, found by Jack Jansen in 2.2 CVS development. + # This version got an assert failure in debug build, infinite loop in + # release build. Unfortunately, provoking this kind of stuff requires + # a mix of inserts and deletes hitting exactly the right hash codes in + # exactly the right order, and I can't think of a randomized approach + # that would be *likely* to hit a failing case in reasonable time. + + d = {} + for i in range(5): + d[i] = i + for i in range(5): + del d[i] + for i in range(5, 9): # i==8 was the problem + d[i] = i + + def test_resize2(self): + # Another dict resizing bug (SF bug #1456209). + # This caused Segmentation faults or Illegal instructions. + + class X(object): + def __hash__(self): + return 5 + def __eq__(self, other): + if resizing: + d.clear() + return False + d = {} + resizing = False + d[X()] = 1 + d[X()] = 2 + d[X()] = 3 + d[X()] = 4 + d[X()] = 5 + # now trigger a resize + resizing = True + d[9] = 6 + from test import mapping_tests Modified: python/branches/p3yk/Lib/test/test_dis.py ============================================================================== --- python/branches/p3yk/Lib/test/test_dis.py (original) +++ python/branches/p3yk/Lib/test/test_dis.py Fri Apr 27 21:54:29 2007 @@ -1,11 +1,11 @@ -from test.test_support import verify, verbose, TestFailed, run_unittest +# Minimal tests for dis module + +from test.test_support import verbose, run_unittest +import unittest import sys import dis import StringIO -# Minimal tests for dis module - -import unittest def _f(a): print(a) Modified: python/branches/p3yk/Lib/test/test_doctest.py ============================================================================== --- python/branches/p3yk/Lib/test/test_doctest.py (original) +++ python/branches/p3yk/Lib/test/test_doctest.py Fri Apr 27 21:54:29 2007 @@ -35,7 +35,7 @@ >>> for i in range(10): ... sc = sc.double() ... print(sc.get(), end=' ') - 6 12 24 48 96 192 384 768 1536 3072 + 6 12 24 48 96 192 384 768 1536 3072 """ def __init__(self, val): """ @@ -571,7 +571,7 @@ ... ... >>> for x in range(10): ... ... print(x, end=' ') - ... 0 1 2 3 4 5 6 7 8 9 + ... 0 1 2 3 4 5 6 7 8 9 ... >>> x//2 ... 6 ... ''' @@ -1461,11 +1461,11 @@ >>> def f(x): r''' ... >>> for x in range(10): # doctest: +ELLIPSIS ... ... print(x, end=' ') - ... 0 1 2 ... 9 + ... 0 1 2 ... 9 ... ... >>> for x in range(10): ... ... print(x, end=' ') # doctest: +ELLIPSIS - ... 0 1 2 ... 9 + ... 0 1 2 ... 9 ... ''' >>> test = doctest.DocTestFinder().find(f)[0] >>> doctest.DocTestRunner(verbose=False).run(test) @@ -1478,7 +1478,7 @@ ... Should fail (option directive not on the last line): ... >>> for x in range(10): # doctest: +ELLIPSIS ... ... print(x, end=' ') # doctest: +NORMALIZE_WHITESPACE - ... 0 1 2...9 + ... 0 1 2...9 ... ''' >>> test = doctest.DocTestFinder().find(f)[0] >>> doctest.DocTestRunner(verbose=False).run(test) Modified: python/branches/p3yk/Lib/test/test_email.py ============================================================================== --- python/branches/p3yk/Lib/test/test_email.py (original) +++ python/branches/p3yk/Lib/test/test_email.py Fri Apr 27 21:54:29 2007 @@ -4,10 +4,10 @@ import unittest # The specific tests now live in Lib/email/test from email.test.test_email import suite -from test.test_support import run_suite +from test import test_support def test_main(): - run_suite(suite()) + test_support.run_unittest(suite()) if __name__ == '__main__': test_main() Modified: python/branches/p3yk/Lib/test/test_email_codecs.py ============================================================================== --- python/branches/p3yk/Lib/test/test_email_codecs.py (original) +++ python/branches/p3yk/Lib/test/test_email_codecs.py Fri Apr 27 21:54:29 2007 @@ -9,7 +9,7 @@ def test_main(): suite = test_email_codecs.suite() suite.addTest(test_email_codecs_renamed.suite()) - test_support.run_suite(suite) + test_support.run_unittest(suite) if __name__ == '__main__': test_main() Modified: python/branches/p3yk/Lib/test/test_email_renamed.py ============================================================================== --- python/branches/p3yk/Lib/test/test_email_renamed.py (original) +++ python/branches/p3yk/Lib/test/test_email_renamed.py Fri Apr 27 21:54:29 2007 @@ -4,10 +4,10 @@ import unittest # The specific tests now live in Lib/email/test from email.test.test_email_renamed import suite -from test.test_support import run_suite +from test import test_support def test_main(): - run_suite(suite()) + test_support.run_unittest(suite()) if __name__ == '__main__': test_main() Modified: python/branches/p3yk/Lib/test/test_exceptions.py ============================================================================== --- python/branches/p3yk/Lib/test/test_exceptions.py (original) +++ python/branches/p3yk/Lib/test/test_exceptions.py Fri Apr 27 21:54:29 2007 @@ -229,6 +229,9 @@ (EnvironmentError, (1, 'strErrorStr', 'filenameStr'), {'message' : '', 'args' : (1, 'strErrorStr'), 'errno' : 1, 'strerror' : 'strErrorStr', 'filename' : 'filenameStr'}), + (SyntaxError, (), {'message' : '', 'msg' : None, 'text' : None, + 'filename' : None, 'lineno' : None, 'offset' : None, + 'print_file_and_line' : None}), (SyntaxError, ('msgStr',), {'message' : 'msgStr', 'args' : ('msgStr',), 'text' : None, 'print_file_and_line' : None, 'msg' : 'msgStr', @@ -337,7 +340,7 @@ def testExceptionCleanup(self): # Make sure "except V as N" exceptions are cleaned up properly - + try: raise Exception() except Exception as e: Modified: python/branches/p3yk/Lib/test/test_fileinput.py ============================================================================== --- python/branches/p3yk/Lib/test/test_fileinput.py (original) +++ python/branches/p3yk/Lib/test/test_fileinput.py Fri Apr 27 21:54:29 2007 @@ -3,7 +3,9 @@ Nick Mathewson ''' -from test.test_support import verify, verbose, TESTFN, TestFailed +import unittest +from test.test_support import verbose, TESTFN, run_unittest +from test.test_support import unlink as safe_unlink import sys, os, re from StringIO import StringIO from fileinput import FileInput, hook_encoded @@ -18,211 +20,206 @@ def writeTmp(i, lines, mode='w'): # opening in text mode is the default name = TESTFN + str(i) f = open(name, mode) - for line in lines: - f.write(line) + f.writelines(lines) f.close() return name -pat = re.compile(r'LINE (\d+) OF FILE (\d+)') - def remove_tempfiles(*names): for name in names: - try: - os.unlink(name) - except: - pass + safe_unlink(name) -def runTests(t1, t2, t3, t4, bs=0, round=0): - start = 1 + round*6 - if verbose: - print('%s. Simple iteration (bs=%s)' % (start+0, bs)) - fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) - lines = list(fi) - fi.close() - verify(len(lines) == 31) - verify(lines[4] == 'Line 5 of file 1\n') - verify(lines[30] == 'Line 1 of file 4\n') - verify(fi.lineno() == 31) - verify(fi.filename() == t4) - - if verbose: - print('%s. Status variables (bs=%s)' % (start+1, bs)) - fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) - s = "x" - while s and s != 'Line 6 of file 2\n': - s = fi.readline() - verify(fi.filename() == t2) - verify(fi.lineno() == 21) - verify(fi.filelineno() == 6) - verify(not fi.isfirstline()) - verify(not fi.isstdin()) - - if verbose: - print('%s. Nextfile (bs=%s)' % (start+2, bs)) - fi.nextfile() - verify(fi.readline() == 'Line 1 of file 3\n') - verify(fi.lineno() == 22) - fi.close() - - if verbose: - print('%s. Stdin (bs=%s)' % (start+3, bs)) - fi = FileInput(files=(t1, t2, t3, t4, '-'), bufsize=bs) - savestdin = sys.stdin - try: - sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n") +class BufferSizesTests(unittest.TestCase): + def test_buffer_sizes(self): + # First, run the tests with default and teeny buffer size. + for round, bs in (0, 0), (1, 30): + try: + t1 = writeTmp(1, ["Line %s of file 1\n" % (i+1) for i in range(15)]) + t2 = writeTmp(2, ["Line %s of file 2\n" % (i+1) for i in range(10)]) + t3 = writeTmp(3, ["Line %s of file 3\n" % (i+1) for i in range(5)]) + t4 = writeTmp(4, ["Line %s of file 4\n" % (i+1) for i in range(1)]) + self.buffer_size_test(t1, t2, t3, t4, bs, round) + finally: + remove_tempfiles(t1, t2, t3, t4) + + def buffer_size_test(self, t1, t2, t3, t4, bs=0, round=0): + pat = re.compile(r'LINE (\d+) OF FILE (\d+)') + + start = 1 + round*6 + if verbose: + print('%s. Simple iteration (bs=%s)' % (start+0, bs)) + fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) lines = list(fi) - verify(len(lines) == 33) - verify(lines[32] == 'Line 2 of stdin\n') - verify(fi.filename() == '') + fi.close() + self.assertEqual(len(lines), 31) + self.assertEqual(lines[4], 'Line 5 of file 1\n') + self.assertEqual(lines[30], 'Line 1 of file 4\n') + self.assertEqual(fi.lineno(), 31) + self.assertEqual(fi.filename(), t4) + + if verbose: + print('%s. Status variables (bs=%s)' % (start+1, bs)) + fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) + s = "x" + while s and s != 'Line 6 of file 2\n': + s = fi.readline() + self.assertEqual(fi.filename(), t2) + self.assertEqual(fi.lineno(), 21) + self.assertEqual(fi.filelineno(), 6) + self.failIf(fi.isfirstline()) + self.failIf(fi.isstdin()) + + if verbose: + print('%s. Nextfile (bs=%s)' % (start+2, bs)) fi.nextfile() - finally: - sys.stdin = savestdin + self.assertEqual(fi.readline(), 'Line 1 of file 3\n') + self.assertEqual(fi.lineno(), 22) + fi.close() - if verbose: - print('%s. Boundary conditions (bs=%s)' % (start+4, bs)) - fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) - verify(fi.lineno() == 0) - verify(fi.filename() == None) - fi.nextfile() - verify(fi.lineno() == 0) - verify(fi.filename() == None) - - if verbose: - print('%s. Inplace (bs=%s)' % (start+5, bs)) - savestdout = sys.stdout - try: - fi = FileInput(files=(t1, t2, t3, t4), inplace=1, bufsize=bs) + if verbose: + print('%s. Stdin (bs=%s)' % (start+3, bs)) + fi = FileInput(files=(t1, t2, t3, t4, '-'), bufsize=bs) + savestdin = sys.stdin + try: + sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n") + lines = list(fi) + self.assertEqual(len(lines), 33) + self.assertEqual(lines[32], 'Line 2 of stdin\n') + self.assertEqual(fi.filename(), '') + fi.nextfile() + finally: + sys.stdin = savestdin + + if verbose: + print('%s. Boundary conditions (bs=%s)' % (start+4, bs)) + fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) + self.assertEqual(fi.lineno(), 0) + self.assertEqual(fi.filename(), None) + fi.nextfile() + self.assertEqual(fi.lineno(), 0) + self.assertEqual(fi.filename(), None) + + if verbose: + print('%s. Inplace (bs=%s)' % (start+5, bs)) + savestdout = sys.stdout + try: + fi = FileInput(files=(t1, t2, t3, t4), inplace=1, bufsize=bs) + for line in fi: + line = line[:-1].upper() + print(line) + fi.close() + finally: + sys.stdout = savestdout + + fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) for line in fi: - line = line[:-1].upper() - print(line) + self.assertEqual(line[-1], '\n') + m = pat.match(line[:-1]) + self.assertNotEqual(m, None) + self.assertEqual(int(m.group(1)), fi.filelineno()) fi.close() - finally: - sys.stdout = savestdout - fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) - for line in fi: - verify(line[-1] == '\n') - m = pat.match(line[:-1]) - verify(m != None) - verify(int(m.group(1)) == fi.filelineno()) - fi.close() - - -def writeFiles(): - global t1, t2, t3, t4 - t1 = writeTmp(1, ["Line %s of file 1\n" % (i+1) for i in range(15)]) - t2 = writeTmp(2, ["Line %s of file 2\n" % (i+1) for i in range(10)]) - t3 = writeTmp(3, ["Line %s of file 3\n" % (i+1) for i in range(5)]) - t4 = writeTmp(4, ["Line %s of file 4\n" % (i+1) for i in range(1)]) - -# First, run the tests with default and teeny buffer size. -for round, bs in (0, 0), (1, 30): - try: - writeFiles() - runTests(t1, t2, t3, t4, bs, round) - finally: - remove_tempfiles(t1, t2, t3, t4) - -# Next, check for proper behavior with 0-byte files. -if verbose: - print("13. 0-byte files") -try: - t1 = writeTmp(1, [""]) - t2 = writeTmp(2, [""]) - t3 = writeTmp(3, ["The only line there is.\n"]) - t4 = writeTmp(4, [""]) - fi = FileInput(files=(t1, t2, t3, t4)) - line = fi.readline() - verify(line == 'The only line there is.\n') - verify(fi.lineno() == 1) - verify(fi.filelineno() == 1) - verify(fi.filename() == t3) - line = fi.readline() - verify(not line) - verify(fi.lineno() == 1) - verify(fi.filelineno() == 0) - verify(fi.filename() == t4) - fi.close() -finally: - remove_tempfiles(t1, t2, t3, t4) - -if verbose: - print("14. Files that don't end with newline") -try: - t1 = writeTmp(1, ["A\nB\nC"]) - t2 = writeTmp(2, ["D\nE\nF"]) - fi = FileInput(files=(t1, t2)) - lines = list(fi) - verify(lines == ["A\n", "B\n", "C", "D\n", "E\n", "F"]) - verify(fi.filelineno() == 3) - verify(fi.lineno() == 6) -finally: - remove_tempfiles(t1, t2) - -if verbose: - print("15. Unicode filenames") -try: - t1 = writeTmp(1, ["A\nB"]) - encoding = sys.getfilesystemencoding() - if encoding is None: - encoding = 'ascii' - fi = FileInput(files=unicode(t1, encoding)) - lines = list(fi) - verify(lines == ["A\n", "B"]) -finally: - remove_tempfiles(t1) - -if verbose: - print("16. fileno()") -try: - t1 = writeTmp(1, ["A\nB"]) - t2 = writeTmp(2, ["C\nD"]) - fi = FileInput(files=(t1, t2)) - verify(fi.fileno() == -1) - line = next(fi) - verify(fi.fileno() != -1) - fi.nextfile() - verify(fi.fileno() == -1) - line = list(fi) - verify(fi.fileno() == -1) -finally: - remove_tempfiles(t1, t2) - -if verbose: - print("17. Specify opening mode") -try: - # invalid mode, should raise ValueError - fi = FileInput(mode="w") - raise TestFailed("FileInput should reject invalid mode argument") -except ValueError: - pass -try: - # try opening in universal newline mode - t1 = writeTmp(1, ["A\nB\r\nC\rD"], mode="wb") - fi = FileInput(files=t1, mode="U") - lines = list(fi) - verify(lines == ["A\n", "B\n", "C\n", "D"]) -finally: - remove_tempfiles(t1) - -if verbose: - print("18. Test file opening hook") -try: - # cannot use openhook and inplace mode - fi = FileInput(inplace=1, openhook=lambda f,m: None) - raise TestFailed("FileInput should raise if both inplace " - "and openhook arguments are given") -except ValueError: - pass -try: - fi = FileInput(openhook=1) - raise TestFailed("FileInput should check openhook for being callable") -except ValueError: - pass -try: - t1 = writeTmp(1, ["A\nB"], mode="wb") - fi = FileInput(files=t1, openhook=hook_encoded("rot13")) - lines = list(fi) - verify(lines == ["N\n", "O"]) -finally: - remove_tempfiles(t1) +class FileInputTests(unittest.TestCase): + def test_zero_byte_files(self): + try: + t1 = writeTmp(1, [""]) + t2 = writeTmp(2, [""]) + t3 = writeTmp(3, ["The only line there is.\n"]) + t4 = writeTmp(4, [""]) + fi = FileInput(files=(t1, t2, t3, t4)) + + line = fi.readline() + self.assertEqual(line, 'The only line there is.\n') + self.assertEqual(fi.lineno(), 1) + self.assertEqual(fi.filelineno(), 1) + self.assertEqual(fi.filename(), t3) + + line = fi.readline() + self.failIf(line) + self.assertEqual(fi.lineno(), 1) + self.assertEqual(fi.filelineno(), 0) + self.assertEqual(fi.filename(), t4) + fi.close() + finally: + remove_tempfiles(t1, t2, t3, t4) + + def test_files_that_dont_end_with_newline(self): + try: + t1 = writeTmp(1, ["A\nB\nC"]) + t2 = writeTmp(2, ["D\nE\nF"]) + fi = FileInput(files=(t1, t2)) + lines = list(fi) + self.assertEqual(lines, ["A\n", "B\n", "C", "D\n", "E\n", "F"]) + self.assertEqual(fi.filelineno(), 3) + self.assertEqual(fi.lineno(), 6) + finally: + remove_tempfiles(t1, t2) + + def test_unicode_filenames(self): + try: + t1 = writeTmp(1, ["A\nB"]) + encoding = sys.getfilesystemencoding() + if encoding is None: + encoding = 'ascii' + fi = FileInput(files=unicode(t1, encoding)) + lines = list(fi) + self.assertEqual(lines, ["A\n", "B"]) + finally: + remove_tempfiles(t1) + + def test_fileno(self): + try: + t1 = writeTmp(1, ["A\nB"]) + t2 = writeTmp(2, ["C\nD"]) + fi = FileInput(files=(t1, t2)) + self.assertEqual(fi.fileno(), -1) + line =next( fi) + self.assertNotEqual(fi.fileno(), -1) + fi.nextfile() + self.assertEqual(fi.fileno(), -1) + line = list(fi) + self.assertEqual(fi.fileno(), -1) + finally: + remove_tempfiles(t1, t2) + + def test_opening_mode(self): + try: + # invalid mode, should raise ValueError + fi = FileInput(mode="w") + self.fail("FileInput should reject invalid mode argument") + except ValueError: + pass + try: + # try opening in universal newline mode + t1 = writeTmp(1, ["A\nB\r\nC\rD"], mode="wb") + fi = FileInput(files=t1, mode="U") + lines = list(fi) + self.assertEqual(lines, ["A\n", "B\n", "C\n", "D"]) + finally: + remove_tempfiles(t1) + + def test_file_opening_hook(self): + try: + # cannot use openhook and inplace mode + fi = FileInput(inplace=1, openhook=lambda f, m: None) + self.fail("FileInput should raise if both inplace " + "and openhook arguments are given") + except ValueError: + pass + try: + fi = FileInput(openhook=1) + self.fail("FileInput should check openhook for being callable") + except ValueError: + pass + try: + t1 = writeTmp(1, ["A\nB"], mode="wb") + fi = FileInput(files=t1, openhook=hook_encoded("rot13")) + lines = list(fi) + self.assertEqual(lines, ["N\n", "O"]) + finally: + remove_tempfiles(t1) + +def test_main(): + run_unittest(BufferSizesTests, FileInputTests) + +if __name__ == "__main__": + test_main() 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 Fri Apr 27 21:54:29 2007 @@ -110,13 +110,13 @@ self.assertEquals(f.writable(), True) self.assertEquals(f.seekable(), True) f.close() - + f = _fileio._FileIO(TESTFN, "r") self.assertEquals(f.readable(), True) self.assertEquals(f.writable(), False) self.assertEquals(f.seekable(), True) f.close() - + f = _fileio._FileIO(TESTFN, "a+") self.assertEquals(f.readable(), True) self.assertEquals(f.writable(), True) Modified: python/branches/p3yk/Lib/test/test_functools.py ============================================================================== --- python/branches/p3yk/Lib/test/test_functools.py (original) +++ python/branches/p3yk/Lib/test/test_functools.py Fri Apr 27 21:54:29 2007 @@ -285,7 +285,7 @@ self.sofar.append(n*n) n += 1 return self.sofar[i] - + self.assertEqual(self.func(lambda x, y: x+y, ['a', 'b', 'c'], ''), 'abc') self.assertEqual( self.func(lambda x, y: x+y, [['a', 'c'], [], ['d', 'w']], []), @@ -321,7 +321,7 @@ return i else: raise IndexError - + from operator import add self.assertEqual(self.func(add, SequenceClass(5)), 10) self.assertEqual(self.func(add, SequenceClass(5), 42), 52) @@ -333,7 +333,7 @@ d = {"one": 1, "two": 2, "three": 3} self.assertEqual(self.func(add, d), "".join(d.keys())) - + def test_main(verbose=None): Modified: python/branches/p3yk/Lib/test/test_gc.py ============================================================================== --- python/branches/p3yk/Lib/test/test_gc.py (original) +++ python/branches/p3yk/Lib/test/test_gc.py Fri Apr 27 21:54:29 2007 @@ -1,390 +1,11 @@ -from test.test_support import verify, verbose, TestFailed, vereq +import unittest +from test.test_support import verbose, run_unittest import sys import gc import weakref -def expect(actual, expected, name): - if actual != expected: - raise TestFailed, "test_%s: actual %r, expected %r" % ( - name, actual, expected) - -def expect_nonzero(actual, name): - if actual == 0: - raise TestFailed, "test_%s: unexpected zero" % name - -def run_test(name, thunk): - if verbose: - print("testing %s..." % name, end=' ') - thunk() - if verbose: - print("ok") - -def test_list(): - l = [] - l.append(l) - gc.collect() - del l - expect(gc.collect(), 1, "list") - -def test_dict(): - d = {} - d[1] = d - gc.collect() - del d - expect(gc.collect(), 1, "dict") - -def test_tuple(): - # since tuples are immutable we close the loop with a list - l = [] - t = (l,) - l.append(t) - gc.collect() - del t - del l - expect(gc.collect(), 2, "tuple") - -def test_class(): - class A: - pass - A.a = A - gc.collect() - del A - expect_nonzero(gc.collect(), "class") - -def test_newstyleclass(): - class A(object): - pass - gc.collect() - del A - expect_nonzero(gc.collect(), "staticclass") - -def test_instance(): - class A: - pass - a = A() - a.a = a - gc.collect() - del a - expect_nonzero(gc.collect(), "instance") - -def test_newinstance(): - class A(object): - pass - a = A() - a.a = a - gc.collect() - del a - expect_nonzero(gc.collect(), "newinstance") - class B(list): - pass - class C(B, A): - pass - a = C() - a.a = a - gc.collect() - del a - expect_nonzero(gc.collect(), "newinstance(2)") - del B, C - expect_nonzero(gc.collect(), "newinstance(3)") - A.a = A() - del A - expect_nonzero(gc.collect(), "newinstance(4)") - expect(gc.collect(), 0, "newinstance(5)") - -def test_method(): - # Tricky: self.__init__ is a bound method, it references the instance. - class A: - def __init__(self): - self.init = self.__init__ - a = A() - gc.collect() - del a - expect_nonzero(gc.collect(), "method") - -def test_finalizer(): - # A() is uncollectable if it is part of a cycle, make sure it shows up - # in gc.garbage. - class A: - def __del__(self): pass - class B: - pass - a = A() - a.a = a - id_a = id(a) - b = B() - b.b = b - gc.collect() - del a - del b - expect_nonzero(gc.collect(), "finalizer") - for obj in gc.garbage: - if id(obj) == id_a: - del obj.a - break - else: - raise TestFailed, "didn't find obj in garbage (finalizer)" - gc.garbage.remove(obj) - -def test_finalizer_newclass(): - # A() is uncollectable if it is part of a cycle, make sure it shows up - # in gc.garbage. - class A(object): - def __del__(self): pass - class B(object): - pass - a = A() - a.a = a - id_a = id(a) - b = B() - b.b = b - gc.collect() - del a - del b - expect_nonzero(gc.collect(), "finalizer") - for obj in gc.garbage: - if id(obj) == id_a: - del obj.a - break - else: - raise TestFailed, "didn't find obj in garbage (finalizer)" - gc.garbage.remove(obj) - -def test_function(): - # Tricky: f -> d -> f, code should call d.clear() after the exec to - # break the cycle. - d = {} - exec("def f(): pass\n", d) - gc.collect() - del d - expect(gc.collect(), 2, "function") - -def test_frame(): - def f(): - frame = sys._getframe() - gc.collect() - f() - expect(gc.collect(), 1, "frame") - - -def test_saveall(): - # Verify that cyclic garbage like lists show up in gc.garbage if the - # SAVEALL option is enabled. - - # First make sure we don't save away other stuff that just happens to - # be waiting for collection. - gc.collect() - vereq(gc.garbage, []) # if this fails, someone else created immortal trash - - L = [] - L.append(L) - id_L = id(L) - - debug = gc.get_debug() - gc.set_debug(debug | gc.DEBUG_SAVEALL) - del L - gc.collect() - gc.set_debug(debug) - - vereq(len(gc.garbage), 1) - obj = gc.garbage.pop() - vereq(id(obj), id_L) - -def test_del(): - # __del__ methods can trigger collection, make this to happen - thresholds = gc.get_threshold() - gc.enable() - gc.set_threshold(1) - - class A: - def __del__(self): - dir(self) - a = A() - del a - - gc.disable() - gc.set_threshold(*thresholds) - -def test_del_newclass(): - # __del__ methods can trigger collection, make this to happen - thresholds = gc.get_threshold() - gc.enable() - gc.set_threshold(1) - - class A(object): - def __del__(self): - dir(self) - a = A() - del a - - gc.disable() - gc.set_threshold(*thresholds) - -def test_get_count(): - gc.collect() - expect(gc.get_count(), (0, 0, 0), "get_count()") - a = dict() - expect(gc.get_count(), (1, 0, 0), "get_count()") - -def test_collect_generations(): - gc.collect() - a = dict() - gc.collect(0) - expect(gc.get_count(), (0, 1, 0), "collect(0)") - gc.collect(1) - expect(gc.get_count(), (0, 0, 1), "collect(1)") - gc.collect(2) - expect(gc.get_count(), (0, 0, 0), "collect(1)") - -class Ouch: - n = 0 - def __del__(self): - Ouch.n = Ouch.n + 1 - if Ouch.n % 17 == 0: - gc.collect() - -def test_trashcan(): - # "trashcan" is a hack to prevent stack overflow when deallocating - # very deeply nested tuples etc. It works in part by abusing the - # type pointer and refcount fields, and that can yield horrible - # problems when gc tries to traverse the structures. - # If this test fails (as it does in 2.0, 2.1 and 2.2), it will - # most likely die via segfault. - - # Note: In 2.3 the possibility for compiling without cyclic gc was - # removed, and that in turn allows the trashcan mechanism to work - # via much simpler means (e.g., it never abuses the type pointer or - # refcount fields anymore). Since it's much less likely to cause a - # problem now, the various constants in this expensive (we force a lot - # of full collections) test are cut back from the 2.2 version. - gc.enable() - N = 150 - for count in range(2): - t = [] - for i in range(N): - t = [t, Ouch()] - u = [] - for i in range(N): - u = [u, Ouch()] - v = {} - for i in range(N): - v = {1: v, 2: Ouch()} - gc.disable() - -class Boom: - def __getattr__(self, someattribute): - del self.attr - raise AttributeError - -def test_boom(): - a = Boom() - b = Boom() - a.attr = b - b.attr = a - - gc.collect() - garbagelen = len(gc.garbage) - del a, b - # a<->b are in a trash cycle now. Collection will invoke Boom.__getattr__ - # (to see whether a and b have __del__ methods), and __getattr__ deletes - # the internal "attr" attributes as a side effect. That causes the - # trash cycle to get reclaimed via refcounts falling to 0, thus mutating - # the trash graph as a side effect of merely asking whether __del__ - # exists. This used to (before 2.3b1) crash Python. Now __getattr__ - # isn't called. - expect(gc.collect(), 4, "boom") - expect(len(gc.garbage), garbagelen, "boom") - -class Boom2: - def __init__(self): - self.x = 0 - - def __getattr__(self, someattribute): - self.x += 1 - if self.x > 1: - del self.attr - raise AttributeError - -def test_boom2(): - a = Boom2() - b = Boom2() - a.attr = b - b.attr = a - - gc.collect() - garbagelen = len(gc.garbage) - del a, b - # Much like test_boom(), except that __getattr__ doesn't break the - # cycle until the second time gc checks for __del__. As of 2.3b1, - # there isn't a second time, so this simply cleans up the trash cycle. - # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get reclaimed - # this way. - expect(gc.collect(), 4, "boom2") - expect(len(gc.garbage), garbagelen, "boom2") - -# boom__new and boom2_new are exactly like boom and boom2, except use -# new-style classes. - -class Boom_New(object): - def __getattr__(self, someattribute): - del self.attr - raise AttributeError - -def test_boom_new(): - a = Boom_New() - b = Boom_New() - a.attr = b - b.attr = a - - gc.collect() - garbagelen = len(gc.garbage) - del a, b - expect(gc.collect(), 4, "boom_new") - expect(len(gc.garbage), garbagelen, "boom_new") - -class Boom2_New(object): - def __init__(self): - self.x = 0 - - def __getattr__(self, someattribute): - self.x += 1 - if self.x > 1: - del self.attr - raise AttributeError - -def test_boom2_new(): - a = Boom2_New() - b = Boom2_New() - a.attr = b - b.attr = a - - gc.collect() - garbagelen = len(gc.garbage) - del a, b - expect(gc.collect(), 4, "boom2_new") - expect(len(gc.garbage), garbagelen, "boom2_new") - -def test_get_referents(): - alist = [1, 3, 5] - got = gc.get_referents(alist) - got.sort() - expect(got, alist, "get_referents") - - atuple = tuple(alist) - got = gc.get_referents(atuple) - got.sort() - expect(got, alist, "get_referents") - - adict = {1: 3, 5: 7} - expected = [1, 3, 5, 7] - got = gc.get_referents(adict) - got.sort() - expect(got, expected, "get_referents") - - got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0)) - got.sort() - expect(got, [0, 0] + range(5), "get_referents") - - expect(gc.get_referents(1, 'a', 4j), [], "get_referents") +### Support code +############################################################################### # Bug 1055820 has several tests of longstanding bugs involving weakrefs and # cyclic gc. @@ -410,217 +31,556 @@ # gc collects it. self.wr = weakref.ref(C1055820(666), it_happened) -def test_bug1055820b(): - # Corresponds to temp2b.py in the bug report. - ouch = [] - def callback(ignored): - ouch[:] = [wr() for wr in WRs] - - Cs = [C1055820(i) for i in range(2)] - WRs = [weakref.ref(c, callback) for c in Cs] - c = None - - gc.collect() - expect(len(ouch), 0, "bug1055820b") - # Make the two instances trash, and collect again. The bug was that - # the callback materialized a strong reference to an instance, but gc - # cleared the instance's dict anyway. - Cs = None - gc.collect() - expect(len(ouch), 2, "bug1055820b") # else the callbacks didn't run - for x in ouch: - # If the callback resurrected one of these guys, the instance - # would be damaged, with an empty __dict__. - expect(x, None, "bug1055820b") - -def test_bug1055820c(): - # Corresponds to temp2c.py in the bug report. This is pretty elaborate. - - c0 = C1055820(0) - # Move c0 into generation 2. - gc.collect() - - c1 = C1055820(1) - c1.keep_c0_alive = c0 - del c0.loop # now only c1 keeps c0 alive - - c2 = C1055820(2) - c2wr = weakref.ref(c2) # no callback! - - ouch = [] - def callback(ignored): - ouch[:] = [c2wr()] - - # The callback gets associated with a wr on an object in generation 2. - c0wr = weakref.ref(c0, callback) - - c0 = c1 = c2 = None - - # What we've set up: c0, c1, and c2 are all trash now. c0 is in - # generation 2. The only thing keeping it alive is that c1 points to it. - # c1 and c2 are in generation 0, and are in self-loops. There's a global - # weakref to c2 (c2wr), but that weakref has no callback. There's also - # a global weakref to c0 (c0wr), and that does have a callback, and that - # callback references c2 via c2wr(). - # - # c0 has a wr with callback, which references c2wr - # ^ - # | - # | Generation 2 above dots - #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . - # | Generation 0 below dots - # | - # | - # ^->c1 ^->c2 has a wr but no callback - # | | | | - # <--v <--v - # - # So this is the nightmare: when generation 0 gets collected, we see that - # c2 has a callback-free weakref, and c1 doesn't even have a weakref. - # Collecting generation 0 doesn't see c0 at all, and c0 is the only object - # that has a weakref with a callback. gc clears c1 and c2. Clearing c1 - # has the side effect of dropping the refcount on c0 to 0, so c0 goes - # away (despite that it's in an older generation) and c0's wr callback - # triggers. That in turn materializes a reference to c2 via c2wr(), but - # c2 gets cleared anyway by gc. - - # We want to let gc happen "naturally", to preserve the distinction - # between generations. - junk = [] - i = 0 - detector = GC_Detector() - while not detector.gc_happened: - i += 1 - if i > 10000: - raise TestFailed("gc didn't happen after 10000 iterations") - expect(len(ouch), 0, "bug1055820c") - junk.append([]) # this will eventually trigger gc - - expect(len(ouch), 1, "bug1055820c") # else the callback wasn't invoked - for x in ouch: - # If the callback resurrected c2, the instance would be damaged, - # with an empty __dict__. - expect(x, None, "bug1055820c") - -def test_bug1055820d(): - # Corresponds to temp2d.py in the bug report. This is very much like - # test_bug1055820c, but uses a __del__ method instead of a weakref - # callback to sneak in a resurrection of cyclic trash. - - ouch = [] - class D(C1055820): - def __del__(self): - ouch[:] = [c2wr()] +### Tests +############################################################################### - d0 = D(0) - # Move all the above into generation 2. - gc.collect() - - c1 = C1055820(1) - c1.keep_d0_alive = d0 - del d0.loop # now only c1 keeps d0 alive - - c2 = C1055820(2) - c2wr = weakref.ref(c2) # no callback! - - d0 = c1 = c2 = None - - # What we've set up: d0, c1, and c2 are all trash now. d0 is in - # generation 2. The only thing keeping it alive is that c1 points to it. - # c1 and c2 are in generation 0, and are in self-loops. There's a global - # weakref to c2 (c2wr), but that weakref has no callback. There are no - # other weakrefs. - # - # d0 has a __del__ method that references c2wr - # ^ - # | - # | Generation 2 above dots - #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . - # | Generation 0 below dots - # | - # | - # ^->c1 ^->c2 has a wr but no callback - # | | | | - # <--v <--v - # - # So this is the nightmare: when generation 0 gets collected, we see that - # c2 has a callback-free weakref, and c1 doesn't even have a weakref. - # Collecting generation 0 doesn't see d0 at all. gc clears c1 and c2. - # Clearing c1 has the side effect of dropping the refcount on d0 to 0, so - # d0 goes away (despite that it's in an older generation) and d0's __del__ - # triggers. That in turn materializes a reference to c2 via c2wr(), but - # c2 gets cleared anyway by gc. - - # We want to let gc happen "naturally", to preserve the distinction - # between generations. - detector = GC_Detector() - junk = [] - i = 0 - while not detector.gc_happened: - i += 1 - if i > 10000: - raise TestFailed("gc didn't happen after 10000 iterations") - expect(len(ouch), 0, "bug1055820d") - junk.append([]) # this will eventually trigger gc - - expect(len(ouch), 1, "bug1055820d") # else __del__ wasn't invoked - for x in ouch: - # If __del__ resurrected c2, the instance would be damaged, with an - # empty __dict__. - expect(x, None, "bug1055820d") - - -def test_all(): - gc.collect() # Delete 2nd generation garbage - run_test("lists", test_list) - run_test("dicts", test_dict) - run_test("tuples", test_tuple) - run_test("classes", test_class) - run_test("new style classes", test_newstyleclass) - run_test("instances", test_instance) - run_test("new instances", test_newinstance) - run_test("methods", test_method) - run_test("functions", test_function) - run_test("frames", test_frame) - run_test("finalizers", test_finalizer) - run_test("finalizers (new class)", test_finalizer_newclass) - run_test("__del__", test_del) - run_test("__del__ (new class)", test_del_newclass) - run_test("get_count()", test_get_count) - run_test("collect(n)", test_collect_generations) - run_test("saveall", test_saveall) - run_test("trashcan", test_trashcan) - run_test("boom", test_boom) - run_test("boom2", test_boom2) - run_test("boom_new", test_boom_new) - run_test("boom2_new", test_boom2_new) - run_test("get_referents", test_get_referents) - run_test("bug1055820b", test_bug1055820b) +class GCTests(unittest.TestCase): + def test_list(self): + l = [] + l.append(l) + gc.collect() + del l + self.assertEqual(gc.collect(), 1) + + def test_dict(self): + d = {} + d[1] = d + gc.collect() + del d + self.assertEqual(gc.collect(), 1) + + def test_tuple(self): + # since tuples are immutable we close the loop with a list + l = [] + t = (l,) + l.append(t) + gc.collect() + del t + del l + self.assertEqual(gc.collect(), 2) + + def test_class(self): + class A: + pass + A.a = A + gc.collect() + del A + self.assertNotEqual(gc.collect(), 0) + + def test_newstyleclass(self): + class A(object): + pass + gc.collect() + del A + self.assertNotEqual(gc.collect(), 0) + + def test_instance(self): + class A: + pass + a = A() + a.a = a + gc.collect() + del a + self.assertNotEqual(gc.collect(), 0) + + def test_newinstance(self): + class A(object): + pass + a = A() + a.a = a + gc.collect() + del a + self.assertNotEqual(gc.collect(), 0) + class B(list): + pass + class C(B, A): + pass + a = C() + a.a = a + gc.collect() + del a + self.assertNotEqual(gc.collect(), 0) + del B, C + self.assertNotEqual(gc.collect(), 0) + A.a = A() + del A + self.assertNotEqual(gc.collect(), 0) + self.assertEqual(gc.collect(), 0) + + def test_method(self): + # Tricky: self.__init__ is a bound method, it references the instance. + class A: + def __init__(self): + self.init = self.__init__ + a = A() + gc.collect() + del a + self.assertNotEqual(gc.collect(), 0) + + def test_finalizer(self): + # A() is uncollectable if it is part of a cycle, make sure it shows up + # in gc.garbage. + class A: + def __del__(self): pass + class B: + pass + a = A() + a.a = a + id_a = id(a) + b = B() + b.b = b + gc.collect() + del a + del b + self.assertNotEqual(gc.collect(), 0) + for obj in gc.garbage: + if id(obj) == id_a: + del obj.a + break + else: + self.fail("didn't find obj in garbage (finalizer)") + gc.garbage.remove(obj) + + def test_finalizer_newclass(self): + # A() is uncollectable if it is part of a cycle, make sure it shows up + # in gc.garbage. + class A(object): + def __del__(self): pass + class B(object): + pass + a = A() + a.a = a + id_a = id(a) + b = B() + b.b = b + gc.collect() + del a + del b + self.assertNotEqual(gc.collect(), 0) + for obj in gc.garbage: + if id(obj) == id_a: + del obj.a + break + else: + self.fail("didn't find obj in garbage (finalizer)") + gc.garbage.remove(obj) + + def test_function(self): + # Tricky: f -> d -> f, code should call d.clear() after the exec to + # break the cycle. + d = {} + exec("def f(): pass\n", d) + gc.collect() + del d + self.assertEqual(gc.collect(), 2) + + def test_frame(self): + def f(): + frame = sys._getframe() + gc.collect() + f() + self.assertEqual(gc.collect(), 1) + + def test_saveall(self): + # Verify that cyclic garbage like lists show up in gc.garbage if the + # SAVEALL option is enabled. + + # First make sure we don't save away other stuff that just happens to + # be waiting for collection. + gc.collect() + # if this fails, someone else created immortal trash + self.assertEqual(gc.garbage, []) + + L = [] + L.append(L) + id_L = id(L) + + debug = gc.get_debug() + gc.set_debug(debug | gc.DEBUG_SAVEALL) + del L + gc.collect() + gc.set_debug(debug) + + self.assertEqual(len(gc.garbage), 1) + obj = gc.garbage.pop() + self.assertEqual(id(obj), id_L) + + def test_del(self): + # __del__ methods can trigger collection, make this to happen + thresholds = gc.get_threshold() + gc.enable() + gc.set_threshold(1) + + class A: + def __del__(self): + dir(self) + a = A() + del a - gc.enable() - try: - run_test("bug1055820c", test_bug1055820c) - finally: gc.disable() + gc.set_threshold(*thresholds) - gc.enable() - try: - run_test("bug1055820d", test_bug1055820d) - finally: + def test_del_newclass(self): + # __del__ methods can trigger collection, make this to happen + thresholds = gc.get_threshold() + gc.enable() + gc.set_threshold(1) + + class A(object): + def __del__(self): + dir(self) + a = A() + del a + + gc.disable() + gc.set_threshold(*thresholds) + + def test_get_count(self): + gc.collect() + self.assertEqual(gc.get_count(), (0, 0, 0)) + a = dict() + self.assertEqual(gc.get_count(), (1, 0, 0)) + + def test_collect_generations(self): + gc.collect() + a = dict() + gc.collect(0) + self.assertEqual(gc.get_count(), (0, 1, 0)) + gc.collect(1) + self.assertEqual(gc.get_count(), (0, 0, 1)) + gc.collect(2) + self.assertEqual(gc.get_count(), (0, 0, 0)) + + def test_trashcan(self): + class Ouch: + n = 0 + def __del__(self): + Ouch.n = Ouch.n + 1 + if Ouch.n % 17 == 0: + gc.collect() + + # "trashcan" is a hack to prevent stack overflow when deallocating + # very deeply nested tuples etc. It works in part by abusing the + # type pointer and refcount fields, and that can yield horrible + # problems when gc tries to traverse the structures. + # If this test fails (as it does in 2.0, 2.1 and 2.2), it will + # most likely die via segfault. + + # Note: In 2.3 the possibility for compiling without cyclic gc was + # removed, and that in turn allows the trashcan mechanism to work + # via much simpler means (e.g., it never abuses the type pointer or + # refcount fields anymore). Since it's much less likely to cause a + # problem now, the various constants in this expensive (we force a lot + # of full collections) test are cut back from the 2.2 version. + gc.enable() + N = 150 + for count in range(2): + t = [] + for i in range(N): + t = [t, Ouch()] + u = [] + for i in range(N): + u = [u, Ouch()] + v = {} + for i in range(N): + v = {1: v, 2: Ouch()} + gc.disable() + + def test_boom(self): + class Boom: + def __getattr__(self, someattribute): + del self.attr + raise AttributeError + + a = Boom() + b = Boom() + a.attr = b + b.attr = a + + gc.collect() + garbagelen = len(gc.garbage) + del a, b + # a<->b are in a trash cycle now. Collection will invoke + # Boom.__getattr__ (to see whether a and b have __del__ methods), and + # __getattr__ deletes the internal "attr" attributes as a side effect. + # That causes the trash cycle to get reclaimed via refcounts falling to + # 0, thus mutating the trash graph as a side effect of merely asking + # whether __del__ exists. This used to (before 2.3b1) crash Python. + # Now __getattr__ isn't called. + self.assertEqual(gc.collect(), 4) + self.assertEqual(len(gc.garbage), garbagelen) + + def test_boom2(self): + class Boom2: + def __init__(self): + self.x = 0 + + def __getattr__(self, someattribute): + self.x += 1 + if self.x > 1: + del self.attr + raise AttributeError + + a = Boom2() + b = Boom2() + a.attr = b + b.attr = a + + gc.collect() + garbagelen = len(gc.garbage) + del a, b + # Much like test_boom(), except that __getattr__ doesn't break the + # cycle until the second time gc checks for __del__. As of 2.3b1, + # there isn't a second time, so this simply cleans up the trash cycle. + # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get + # reclaimed this way. + self.assertEqual(gc.collect(), 4) + self.assertEqual(len(gc.garbage), garbagelen) + + def test_boom_new(self): + # boom__new and boom2_new are exactly like boom and boom2, except use + # new-style classes. + + class Boom_New(object): + def __getattr__(self, someattribute): + del self.attr + raise AttributeError + + a = Boom_New() + b = Boom_New() + a.attr = b + b.attr = a + + gc.collect() + garbagelen = len(gc.garbage) + del a, b + self.assertEqual(gc.collect(), 4) + self.assertEqual(len(gc.garbage), garbagelen) + + def test_boom2_new(self): + class Boom2_New(object): + def __init__(self): + self.x = 0 + + def __getattr__(self, someattribute): + self.x += 1 + if self.x > 1: + del self.attr + raise AttributeError + + a = Boom2_New() + b = Boom2_New() + a.attr = b + b.attr = a + + gc.collect() + garbagelen = len(gc.garbage) + del a, b + self.assertEqual(gc.collect(), 4) + self.assertEqual(len(gc.garbage), garbagelen) + + def test_get_referents(self): + alist = [1, 3, 5] + got = gc.get_referents(alist) + got.sort() + self.assertEqual(got, alist) + + atuple = tuple(alist) + got = gc.get_referents(atuple) + got.sort() + self.assertEqual(got, alist) + + adict = {1: 3, 5: 7} + expected = [1, 3, 5, 7] + got = gc.get_referents(adict) + got.sort() + self.assertEqual(got, expected) + + got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0)) + got.sort() + self.assertEqual(got, [0, 0] + range(5)) + + self.assertEqual(gc.get_referents(1, 'a', 4j), []) + + def test_bug1055820b(self): + # Corresponds to temp2b.py in the bug report. + + ouch = [] + def callback(ignored): + ouch[:] = [wr() for wr in WRs] + + Cs = [C1055820(i) for i in range(2)] + WRs = [weakref.ref(c, callback) for c in Cs] + c = None + + gc.collect() + self.assertEqual(len(ouch), 0) + # Make the two instances trash, and collect again. The bug was that + # the callback materialized a strong reference to an instance, but gc + # cleared the instance's dict anyway. + Cs = None + gc.collect() + self.assertEqual(len(ouch), 2) # else the callbacks didn't run + for x in ouch: + # If the callback resurrected one of these guys, the instance + # would be damaged, with an empty __dict__. + self.assertEqual(x, None) + +class GCTogglingTests(unittest.TestCase): + def setUp(self): + gc.enable() + + def tearDown(self): gc.disable() -def test(): - if verbose: - print("disabling automatic collection") + def test_bug1055820c(self): + # Corresponds to temp2c.py in the bug report. This is pretty + # elaborate. + + c0 = C1055820(0) + # Move c0 into generation 2. + gc.collect() + + c1 = C1055820(1) + c1.keep_c0_alive = c0 + del c0.loop # now only c1 keeps c0 alive + + c2 = C1055820(2) + c2wr = weakref.ref(c2) # no callback! + + ouch = [] + def callback(ignored): + ouch[:] = [c2wr()] + + # The callback gets associated with a wr on an object in generation 2. + c0wr = weakref.ref(c0, callback) + + c0 = c1 = c2 = None + + # What we've set up: c0, c1, and c2 are all trash now. c0 is in + # generation 2. The only thing keeping it alive is that c1 points to + # it. c1 and c2 are in generation 0, and are in self-loops. There's a + # global weakref to c2 (c2wr), but that weakref has no callback. + # There's also a global weakref to c0 (c0wr), and that does have a + # callback, and that callback references c2 via c2wr(). + # + # c0 has a wr with callback, which references c2wr + # ^ + # | + # | Generation 2 above dots + #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . + # | Generation 0 below dots + # | + # | + # ^->c1 ^->c2 has a wr but no callback + # | | | | + # <--v <--v + # + # So this is the nightmare: when generation 0 gets collected, we see + # that c2 has a callback-free weakref, and c1 doesn't even have a + # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is + # the only object that has a weakref with a callback. gc clears c1 + # and c2. Clearing c1 has the side effect of dropping the refcount on + # c0 to 0, so c0 goes away (despite that it's in an older generation) + # and c0's wr callback triggers. That in turn materializes a reference + # to c2 via c2wr(), but c2 gets cleared anyway by gc. + + # We want to let gc happen "naturally", to preserve the distinction + # between generations. + junk = [] + i = 0 + detector = GC_Detector() + while not detector.gc_happened: + i += 1 + if i > 10000: + self.fail("gc didn't happen after 10000 iterations") + self.assertEqual(len(ouch), 0) + junk.append([]) # this will eventually trigger gc + + self.assertEqual(len(ouch), 1) # else the callback wasn't invoked + for x in ouch: + # If the callback resurrected c2, the instance would be damaged, + # with an empty __dict__. + self.assertEqual(x, None) + + def test_bug1055820d(self): + # Corresponds to temp2d.py in the bug report. This is very much like + # test_bug1055820c, but uses a __del__ method instead of a weakref + # callback to sneak in a resurrection of cyclic trash. + + ouch = [] + class D(C1055820): + def __del__(self): + ouch[:] = [c2wr()] + + d0 = D(0) + # Move all the above into generation 2. + gc.collect() + + c1 = C1055820(1) + c1.keep_d0_alive = d0 + del d0.loop # now only c1 keeps d0 alive + + c2 = C1055820(2) + c2wr = weakref.ref(c2) # no callback! + + d0 = c1 = c2 = None + + # What we've set up: d0, c1, and c2 are all trash now. d0 is in + # generation 2. The only thing keeping it alive is that c1 points to + # it. c1 and c2 are in generation 0, and are in self-loops. There's + # a global weakref to c2 (c2wr), but that weakref has no callback. + # There are no other weakrefs. + # + # d0 has a __del__ method that references c2wr + # ^ + # | + # | Generation 2 above dots + #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . + # | Generation 0 below dots + # | + # | + # ^->c1 ^->c2 has a wr but no callback + # | | | | + # <--v <--v + # + # So this is the nightmare: when generation 0 gets collected, we see + # that c2 has a callback-free weakref, and c1 doesn't even have a + # weakref. Collecting generation 0 doesn't see d0 at all. gc clears + # c1 and c2. Clearing c1 has the side effect of dropping the refcount + # on d0 to 0, so d0 goes away (despite that it's in an older + # generation) and d0's __del__ triggers. That in turn materializes + # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc. + + # We want to let gc happen "naturally", to preserve the distinction + # between generations. + detector = GC_Detector() + junk = [] + i = 0 + while not detector.gc_happened: + i += 1 + if i > 10000: + self.fail("gc didn't happen after 10000 iterations") + self.assertEqual(len(ouch), 0) + junk.append([]) # this will eventually trigger gc + + self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked + for x in ouch: + # If __del__ resurrected c2, the instance would be damaged, with an + # empty __dict__. + self.assertEqual(x, None) + +def test_main(): enabled = gc.isenabled() gc.disable() - verify(not gc.isenabled()) + assert not gc.isenabled() debug = gc.get_debug() gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak try: - test_all() + gc.collect() # Delete 2nd generation garbage + run_unittest(GCTests, GCTogglingTests) finally: gc.set_debug(debug) # test gc.enable() even if GC is disabled by default @@ -628,9 +588,9 @@ print("restoring automatic collection") # make sure to always test gc.enable() gc.enable() - verify(gc.isenabled()) + assert gc.isenabled() if not enabled: gc.disable() - -test() +if __name__ == "__main__": + test_main() Modified: python/branches/p3yk/Lib/test/test_getopt.py ============================================================================== --- python/branches/p3yk/Lib/test/test_getopt.py (original) +++ python/branches/p3yk/Lib/test/test_getopt.py Fri Apr 27 21:54:29 2007 @@ -1,180 +1,179 @@ # test_getopt.py # David Goodger 2000-08-19 +from test.test_support import verbose, run_doctest, run_unittest +import unittest + import getopt -from getopt import GetoptError -from test.test_support import verify, verbose, run_doctest import os -def expectException(teststr, expected, failure=AssertionError): - """Executes a statement passed in teststr, and raises an exception - (failure) if the expected exception is *not* raised.""" - try: - exec(teststr) - except expected: - pass - else: - raise failure - -old_posixly_correct = os.environ.get("POSIXLY_CORRECT") -if old_posixly_correct is not None: - del os.environ["POSIXLY_CORRECT"] - -if verbose: - print('Running tests on getopt.short_has_arg') -verify(getopt.short_has_arg('a', 'a:')) -verify(not getopt.short_has_arg('a', 'a')) -expectException("tmp = getopt.short_has_arg('a', 'b')", GetoptError) -expectException("tmp = getopt.short_has_arg('a', '')", GetoptError) - -if verbose: - print('Running tests on getopt.long_has_args') -has_arg, option = getopt.long_has_args('abc', ['abc=']) -verify(has_arg) -verify(option == 'abc') -has_arg, option = getopt.long_has_args('abc', ['abc']) -verify(not has_arg) -verify(option == 'abc') -has_arg, option = getopt.long_has_args('abc', ['abcd']) -verify(not has_arg) -verify(option == 'abcd') -expectException("has_arg, option = getopt.long_has_args('abc', ['def'])", - GetoptError) -expectException("has_arg, option = getopt.long_has_args('abc', [])", - GetoptError) -expectException("has_arg, option = " + \ - "getopt.long_has_args('abc', ['abcd','abcde'])", - GetoptError) - -if verbose: - print('Running tests on getopt.do_shorts') -opts, args = getopt.do_shorts([], 'a', 'a', []) -verify(opts == [('-a', '')]) -verify(args == []) -opts, args = getopt.do_shorts([], 'a1', 'a:', []) -verify(opts == [('-a', '1')]) -verify(args == []) -#opts, args = getopt.do_shorts([], 'a=1', 'a:', []) -#verify(opts == [('-a', '1')]) -#verify(args == []) -opts, args = getopt.do_shorts([], 'a', 'a:', ['1']) -verify(opts == [('-a', '1')]) -verify(args == []) -opts, args = getopt.do_shorts([], 'a', 'a:', ['1', '2']) -verify(opts == [('-a', '1')]) -verify(args == ['2']) -expectException("opts, args = getopt.do_shorts([], 'a1', 'a', [])", - GetoptError) -expectException("opts, args = getopt.do_shorts([], 'a', 'a:', [])", - GetoptError) - -if verbose: - print('Running tests on getopt.do_longs') -opts, args = getopt.do_longs([], 'abc', ['abc'], []) -verify(opts == [('--abc', '')]) -verify(args == []) -opts, args = getopt.do_longs([], 'abc=1', ['abc='], []) -verify(opts == [('--abc', '1')]) -verify(args == []) -opts, args = getopt.do_longs([], 'abc=1', ['abcd='], []) -verify(opts == [('--abcd', '1')]) -verify(args == []) -opts, args = getopt.do_longs([], 'abc', ['ab', 'abc', 'abcd'], []) -verify(opts == [('--abc', '')]) -verify(args == []) -# Much like the preceding, except with a non-alpha character ("-") in -# option name that precedes "="; failed in -# http://sourceforge.net/bugs/?func=detailbug&bug_id=126863&group_id=5470 -opts, args = getopt.do_longs([], 'foo=42', ['foo-bar', 'foo=',], []) -verify(opts == [('--foo', '42')]) -verify(args == []) -expectException("opts, args = getopt.do_longs([], 'abc=1', ['abc'], [])", - GetoptError) -expectException("opts, args = getopt.do_longs([], 'abc', ['abc='], [])", - GetoptError) - -# note: the empty string between '-a' and '--beta' is significant: -# it simulates an empty string option argument ('-a ""') on the command line. -cmdline = ['-a', '1', '-b', '--alpha=2', '--beta', '-a', '3', '-a', '', - '--beta', 'arg1', 'arg2'] - -if verbose: - print('Running tests on getopt.getopt') -opts, args = getopt.getopt(cmdline, 'a:b', ['alpha=', 'beta']) -verify(opts == [('-a', '1'), ('-b', ''), ('--alpha', '2'), ('--beta', ''), - ('-a', '3'), ('-a', ''), ('--beta', '')] ) -# Note ambiguity of ('-b', '') and ('-a', '') above. This must be -# accounted for in the code that calls getopt(). -verify(args == ['arg1', 'arg2']) - -expectException( - "opts, args = getopt.getopt(cmdline, 'a:b', ['alpha', 'beta'])", - GetoptError) - -# Test handling of GNU style scanning mode. -if verbose: - print('Running tests on getopt.gnu_getopt') -cmdline = ['-a', 'arg1', '-b', '1', '--alpha', '--beta=2'] -# GNU style -opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) -verify(opts == [('-a', ''), ('-b', '1'), ('--alpha', ''), ('--beta', '2')]) -verify(args == ['arg1']) -# Posix style via + -opts, args = getopt.gnu_getopt(cmdline, '+ab:', ['alpha', 'beta=']) -verify(opts == [('-a', '')]) -verify(args == ['arg1', '-b', '1', '--alpha', '--beta=2']) -# Posix style via POSIXLY_CORRECT -os.environ["POSIXLY_CORRECT"] = "1" -opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) -verify(opts == [('-a', '')]) -verify(args == ['arg1', '-b', '1', '--alpha', '--beta=2']) - - -if old_posixly_correct is None: - del os.environ["POSIXLY_CORRECT"] -else: - os.environ["POSIXLY_CORRECT"] = old_posixly_correct - -#------------------------------------------------------------------------------ - -libreftest = """ -Examples from the Library Reference: Doc/lib/libgetopt.tex - -An example using only Unix style options: - - ->>> import getopt ->>> args = '-a -b -cfoo -d bar a1 a2'.split() ->>> args -['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2'] ->>> optlist, args = getopt.getopt(args, 'abc:d:') ->>> optlist -[('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')] ->>> args -['a1', 'a2'] - -Using long option names is equally easy: - - ->>> s = '--condition=foo --testing --output-file abc.def -x a1 a2' ->>> args = s.split() ->>> args -['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2'] ->>> optlist, args = getopt.getopt(args, 'x', [ -... 'condition=', 'output-file=', 'testing']) ->>> optlist -[('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')] ->>> args -['a1', 'a2'] - -""" - -__test__ = {'libreftest' : libreftest} +sentinel = object() + +class GetoptTests(unittest.TestCase): + def setUp(self): + self.old_posixly_correct = os.environ.get("POSIXLY_CORRECT", sentinel) + if self.old_posixly_correct is not sentinel: + del os.environ["POSIXLY_CORRECT"] + + def tearDown(self): + if self.old_posixly_correct is sentinel: + os.environ.pop("POSIXLY_CORRECT", None) + else: + os.environ["POSIXLY_CORRECT"] = self.old_posixly_correct + + def assertError(self, *args, **kwargs): + self.assertRaises(getopt.GetoptError, *args, **kwargs) + + def test_short_has_arg(self): + self.failUnless(getopt.short_has_arg('a', 'a:')) + self.failIf(getopt.short_has_arg('a', 'a')) + self.assertError(getopt.short_has_arg, 'a', 'b') + + def test_long_has_args(self): + has_arg, option = getopt.long_has_args('abc', ['abc=']) + self.failUnless(has_arg) + self.assertEqual(option, 'abc') + + has_arg, option = getopt.long_has_args('abc', ['abc']) + self.failIf(has_arg) + self.assertEqual(option, 'abc') + + has_arg, option = getopt.long_has_args('abc', ['abcd']) + self.failIf(has_arg) + self.assertEqual(option, 'abcd') + + self.assertError(getopt.long_has_args, 'abc', ['def']) + self.assertError(getopt.long_has_args, 'abc', []) + self.assertError(getopt.long_has_args, 'abc', ['abcd','abcde']) + + def test_do_shorts(self): + opts, args = getopt.do_shorts([], 'a', 'a', []) + self.assertEqual(opts, [('-a', '')]) + self.assertEqual(args, []) + + opts, args = getopt.do_shorts([], 'a1', 'a:', []) + self.assertEqual(opts, [('-a', '1')]) + self.assertEqual(args, []) + + #opts, args = getopt.do_shorts([], 'a=1', 'a:', []) + #self.assertEqual(opts, [('-a', '1')]) + #self.assertEqual(args, []) + + opts, args = getopt.do_shorts([], 'a', 'a:', ['1']) + self.assertEqual(opts, [('-a', '1')]) + self.assertEqual(args, []) + + opts, args = getopt.do_shorts([], 'a', 'a:', ['1', '2']) + self.assertEqual(opts, [('-a', '1')]) + self.assertEqual(args, ['2']) + + self.assertError(getopt.do_shorts, [], 'a1', 'a', []) + self.assertError(getopt.do_shorts, [], 'a', 'a:', []) + + def test_do_longs(self): + opts, args = getopt.do_longs([], 'abc', ['abc'], []) + self.assertEqual(opts, [('--abc', '')]) + self.assertEqual(args, []) + + opts, args = getopt.do_longs([], 'abc=1', ['abc='], []) + self.assertEqual(opts, [('--abc', '1')]) + self.assertEqual(args, []) + + opts, args = getopt.do_longs([], 'abc=1', ['abcd='], []) + self.assertEqual(opts, [('--abcd', '1')]) + self.assertEqual(args, []) + + opts, args = getopt.do_longs([], 'abc', ['ab', 'abc', 'abcd'], []) + self.assertEqual(opts, [('--abc', '')]) + self.assertEqual(args, []) + + # Much like the preceding, except with a non-alpha character ("-") in + # option name that precedes "="; failed in + # http://python.org/sf/126863 + opts, args = getopt.do_longs([], 'foo=42', ['foo-bar', 'foo=',], []) + self.assertEqual(opts, [('--foo', '42')]) + self.assertEqual(args, []) + + self.assertError(getopt.do_longs, [], 'abc=1', ['abc'], []) + self.assertError(getopt.do_longs, [], 'abc', ['abc='], []) + + def test_getopt(self): + # note: the empty string between '-a' and '--beta' is significant: + # it simulates an empty string option argument ('-a ""') on the + # command line. + cmdline = ['-a', '1', '-b', '--alpha=2', '--beta', '-a', '3', '-a', + '', '--beta', 'arg1', 'arg2'] + + opts, args = getopt.getopt(cmdline, 'a:b', ['alpha=', 'beta']) + self.assertEqual(opts, [('-a', '1'), ('-b', ''), + ('--alpha', '2'), ('--beta', ''), + ('-a', '3'), ('-a', ''), ('--beta', '')]) + # Note ambiguity of ('-b', '') and ('-a', '') above. This must be + # accounted for in the code that calls getopt(). + self.assertEqual(args, ['arg1', 'arg2']) + + self.assertError(getopt.getopt, cmdline, 'a:b', ['alpha', 'beta']) + + def test_gnu_getopt(self): + # Test handling of GNU style scanning mode. + cmdline = ['-a', 'arg1', '-b', '1', '--alpha', '--beta=2'] + + # GNU style + opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) + self.assertEqual(args, ['arg1']) + self.assertEqual(opts, [('-a', ''), ('-b', '1'), + ('--alpha', ''), ('--beta', '2')]) + + # Posix style via + + opts, args = getopt.gnu_getopt(cmdline, '+ab:', ['alpha', 'beta=']) + self.assertEqual(opts, [('-a', '')]) + self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2']) + + # Posix style via POSIXLY_CORRECT + os.environ["POSIXLY_CORRECT"] = "1" + opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) + self.assertEqual(opts, [('-a', '')]) + self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2']) + + def test_libref_examples(self): + s = """ + Examples from the Library Reference: Doc/lib/libgetopt.tex + + An example using only Unix style options: + + + >>> import getopt + >>> args = '-a -b -cfoo -d bar a1 a2'.split() + >>> args + ['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2'] + >>> optlist, args = getopt.getopt(args, 'abc:d:') + >>> optlist + [('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')] + >>> args + ['a1', 'a2'] + + Using long option names is equally easy: + + + >>> s = '--condition=foo --testing --output-file abc.def -x a1 a2' + >>> args = s.split() + >>> args + ['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2'] + >>> optlist, args = getopt.getopt(args, 'x', [ + ... 'condition=', 'output-file=', 'testing']) + >>> optlist + [('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')] + >>> args + ['a1', 'a2'] + """ + + import new + m = new.module("libreftest", s) + run_doctest(m, verbose) -import sys -run_doctest(sys.modules[__name__], verbose) -#------------------------------------------------------------------------------ +def test_main(): + run_unittest(GetoptTests) -if verbose: - print("Module getopt: tests completed successfully.") +if __name__ == "__main__": + test_main() Modified: python/branches/p3yk/Lib/test/test_gettext.py ============================================================================== --- python/branches/p3yk/Lib/test/test_gettext.py (original) +++ python/branches/p3yk/Lib/test/test_gettext.py Fri Apr 27 21:54:29 2007 @@ -4,7 +4,7 @@ import gettext import unittest -from test.test_support import run_suite +from test import test_support # TODO: @@ -336,19 +336,8 @@ 'John Doe \nJane Foobar ') -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(GettextTestCase1)) - suite.addTest(unittest.makeSuite(GettextTestCase2)) - suite.addTest(unittest.makeSuite(PluralFormsTestCase)) - suite.addTest(unittest.makeSuite(UnicodeTranslationsTest)) - suite.addTest(unittest.makeSuite(WeirdMetadataTest)) - return suite - - def test_main(): - run_suite(suite()) - + test_support.run_unittest(__name__) if __name__ == '__main__': test_main() Modified: python/branches/p3yk/Lib/test/test_glob.py ============================================================================== --- python/branches/p3yk/Lib/test/test_glob.py (original) +++ python/branches/p3yk/Lib/test/test_glob.py Fri Apr 27 21:54:29 2007 @@ -52,6 +52,16 @@ eq(self.glob('aab'), [self.norm('aab')]) eq(self.glob('zymurgy'), []) + # test return types are unicode, but only if os.listdir + # returns unicode filenames + uniset = set([unicode]) + tmp = os.listdir(u'.') + if set(type(x) for x in tmp) == uniset: + u1 = glob.glob(u'*') + u2 = glob.glob(u'./*') + self.assertEquals(set(type(r) for r in u1), uniset) + self.assertEquals(set(type(r) for r in u2), uniset) + def test_glob_one_directory(self): eq = self.assertSequencesEqual_noorder eq(self.glob('a*'), map(self.norm, ['a', 'aab', 'aaa'])) 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 Fri Apr 27 21:54:29 2007 @@ -364,7 +364,7 @@ x = 1; pass; del x; foo() - ### small_stmt: expr_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt + ### small_stmt: expr_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt # Tested below def testExprStmt(self): Modified: python/branches/p3yk/Lib/test/test_htmlparser.py ============================================================================== --- python/branches/p3yk/Lib/test/test_htmlparser.py (original) +++ python/branches/p3yk/Lib/test/test_htmlparser.py Fri Apr 27 21:54:29 2007 @@ -309,6 +309,11 @@ ("endtag", "script"), ]) + def test_entityrefs_in_attributes(self): + self._run_check("", [ + ("starttag", "html", [("foo", u"\u20AC&aa&unsupported;")]) + ]) + def test_main(): test_support.run_unittest(HTMLParserTestCase) Modified: python/branches/p3yk/Lib/test/test_httplib.py ============================================================================== --- python/branches/p3yk/Lib/test/test_httplib.py (original) +++ python/branches/p3yk/Lib/test/test_httplib.py Fri Apr 27 21:54:29 2007 @@ -1,6 +1,7 @@ import httplib import StringIO import sys +import socket from unittest import TestCase @@ -149,8 +150,52 @@ def test_responses(self): self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found") +PORT = 50003 +HOST = "localhost" + +class TimeoutTest(TestCase): + + def setUp(self): + self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + global PORT + PORT = test_support.bind_port(self.serv, HOST, PORT) + self.serv.listen(5) + + def tearDown(self): + self.serv.close() + self.serv = None + + def testTimeoutAttribute(self): + '''This will prove that the timeout gets through + HTTPConnection and into the socket. + ''' + # default + httpConn = httplib.HTTPConnection(HOST, PORT) + httpConn.connect() + self.assertTrue(httpConn.sock.gettimeout() is None) + httpConn.close() + + # a value + httpConn = httplib.HTTPConnection(HOST, PORT, timeout=30) + httpConn.connect() + self.assertEqual(httpConn.sock.gettimeout(), 30) + httpConn.close() + + # None, having other default + previous = socket.getdefaulttimeout() + socket.setdefaulttimeout(30) + try: + httpConn = httplib.HTTPConnection(HOST, PORT, timeout=None) + httpConn.connect() + finally: + socket.setdefaulttimeout(previous) + self.assertEqual(httpConn.sock.gettimeout(), 30) + httpConn.close() + + def test_main(verbose=None): - test_support.run_unittest(HeaderTests, OfflineTest, BasicTest) + test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest) if __name__ == '__main__': test_main() Modified: python/branches/p3yk/Lib/test/test_import.py ============================================================================== --- python/branches/p3yk/Lib/test/test_import.py (original) +++ python/branches/p3yk/Lib/test/test_import.py Fri Apr 27 21:54:29 2007 @@ -193,6 +193,16 @@ if TESTFN in sys.modules: del sys.modules[TESTFN] + def test_infinite_reload(self): + # Bug #742342 reports that Python segfaults (infinite recursion in C) + # when faced with self-recursive reload()ing. + + sys.path.insert(0, os.path.dirname(__file__)) + try: + import infinite_reload + finally: + sys.path.pop(0) + def test_import_name_binding(self): # import x.y.z binds x in the current namespace import test as x Modified: python/branches/p3yk/Lib/test/test_itertools.py ============================================================================== --- python/branches/p3yk/Lib/test/test_itertools.py (original) +++ python/branches/p3yk/Lib/test/test_itertools.py Fri Apr 27 21:54:29 2007 @@ -215,20 +215,20 @@ self.assertEqual(list(izip_longest(*args, **{})), target) target = [tuple((e is None and 'X' or e) for e in t) for t in target] # Replace None fills with 'X' self.assertEqual(list(izip_longest(*args, **dict(fillvalue='X'))), target) - + self.assertEqual(take(3,izip_longest('abcdef', count())), list(zip('abcdef', range(3)))) # take 3 from infinite input self.assertEqual(list(izip_longest()), list(zip())) self.assertEqual(list(izip_longest([])), list(zip([]))) self.assertEqual(list(izip_longest('abcdef')), list(zip('abcdef'))) - + self.assertEqual(list(izip_longest('abc', 'defg', **{})), map(None, 'abc', 'defg')) # empty keyword dict self.assertRaises(TypeError, izip_longest, 3) self.assertRaises(TypeError, izip_longest, range(3), 3) for stmt in [ "izip_longest('abc', fv=1)", - "izip_longest('abc', fillvalue=1, bogus_keyword=None)", + "izip_longest('abc', fillvalue=1, bogus_keyword=None)", ]: try: eval(stmt, globals(), locals()) @@ -236,7 +236,7 @@ pass else: self.fail('Did not raise Type in: ' + stmt) - + # Check tuple re-use (implementation detail) self.assertEqual([tuple(list(pair)) for pair in izip_longest('abc', 'def')], list(zip('abc', 'def'))) @@ -818,7 +818,7 @@ >>> amounts = [120.15, 764.05, 823.14] >>> for checknum, amount in izip(count(1200), amounts): ... print('Check %d is for $%.2f' % (checknum, amount)) -... +... Check 1200 is for $120.15 Check 1201 is for $764.05 Check 1202 is for $823.14 @@ -826,7 +826,7 @@ >>> import operator >>> for cube in imap(operator.pow, xrange(1,4), repeat(3)): ... print(cube) -... +... 1 8 27 @@ -834,7 +834,7 @@ >>> reportlines = ['EuroPython', 'Roster', '', 'alex', '', 'laura', '', 'martin', '', 'walter', '', 'samuele'] >>> for name in islice(reportlines, 3, None, 2): ... print(name.title()) -... +... Alex Laura Martin @@ -846,7 +846,7 @@ >>> di = sorted(sorted(d.items()), key=itemgetter(1)) >>> for k, g in groupby(di, itemgetter(1)): ... print(k, map(itemgetter(0), g)) -... +... 1 ['a', 'c', 'e'] 2 ['b', 'd', 'f'] 3 ['g'] @@ -857,7 +857,7 @@ >>> data = [ 1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28] >>> for k, g in groupby(enumerate(data), lambda (i,x):i-x): ... print(map(operator.itemgetter(1), g)) -... +... [1] [4, 5, 6] [10] Modified: python/branches/p3yk/Lib/test/test_keywordonlyarg.py ============================================================================== --- python/branches/p3yk/Lib/test/test_keywordonlyarg.py (original) +++ python/branches/p3yk/Lib/test/test_keywordonlyarg.py Fri Apr 27 21:54:29 2007 @@ -71,7 +71,7 @@ fundef3 += "i%d, "%i fundef3 += "lastarg):\n pass\n" compile(fundef3, "", "single") - + def testSyntaxErrorForFunctionCall(self): self.assertRaisesSyntaxError("f(p, k=1, p2)") self.assertRaisesSyntaxError("f(p, *(1,2), k1=100)") Modified: python/branches/p3yk/Lib/test/test_locale.py ============================================================================== --- python/branches/p3yk/Lib/test/test_locale.py (original) +++ python/branches/p3yk/Lib/test/test_locale.py Fri Apr 27 21:54:29 2007 @@ -7,7 +7,7 @@ oldlocale = locale.setlocale(locale.LC_NUMERIC) if sys.platform.startswith("win"): - tlocs = ("en",) + tlocs = ("En", "English") else: tlocs = ("en_US.UTF-8", "en_US.US-ASCII", "en_US") Modified: python/branches/p3yk/Lib/test/test_logging.py ============================================================================== --- python/branches/p3yk/Lib/test/test_logging.py (original) +++ python/branches/p3yk/Lib/test/test_logging.py Fri Apr 27 21:54:29 2007 @@ -554,6 +554,8 @@ except KeyError: logging.exception("just testing") os.remove(fn) + hdlr = logging.getLogger().handlers[0] + logging.getLogger().handlers.remove(hdlr) finally: logging._acquireLock() try: Modified: python/branches/p3yk/Lib/test/test_long_future.py ============================================================================== --- python/branches/p3yk/Lib/test/test_long_future.py (original) +++ python/branches/p3yk/Lib/test/test_long_future.py Fri Apr 27 21:54:29 2007 @@ -3,53 +3,53 @@ # test_long.py instead. In the meantime, it's too obscure to try to # trick just part of test_long into using future division. -from test.test_support import TestFailed, verify, verbose +import unittest +from test.test_support import run_unittest -def test_true_division(): - if verbose: - print("long true division") - huge = 1 << 40000 - mhuge = -huge - verify(huge / huge == 1.0) - verify(mhuge / mhuge == 1.0) - verify(huge / mhuge == -1.0) - verify(mhuge / huge == -1.0) - verify(1 / huge == 0.0) - verify(1 / huge == 0.0) - verify(1 / mhuge == 0.0) - verify(1 / mhuge == 0.0) - verify((666 * huge + (huge >> 1)) / huge == 666.5) - verify((666 * mhuge + (mhuge >> 1)) / mhuge == 666.5) - verify((666 * huge + (huge >> 1)) / mhuge == -666.5) - verify((666 * mhuge + (mhuge >> 1)) / huge == -666.5) - verify(huge / (huge << 1) == 0.5) - verify((1000000 * huge) / huge == 1000000) - - namespace = {'huge': huge, 'mhuge': mhuge} - - for overflow in ["float(huge)", "float(mhuge)", - "huge / 1", "huge / 2", "huge / -1", "huge / -2", - "mhuge / 100", "mhuge / 100"]: - try: - eval(overflow, namespace) - except OverflowError: - pass - else: - raise TestFailed("expected OverflowError from %r" % overflow) - - for underflow in ["1 / huge", "2 / huge", "-1 / huge", "-2 / huge", - "100 / mhuge", "100 / mhuge"]: - result = eval(underflow, namespace) - if result != 0.0: - raise TestFailed("expected underflow to 0 from %r" % underflow) - - for zero in ["huge / 0", "huge / 0", - "mhuge / 0", "mhuge / 0"]: - try: - eval(zero, namespace) - except ZeroDivisionError: - pass - else: - raise TestFailed("expected ZeroDivisionError from %r" % zero) +class TrueDivisionTests(unittest.TestCase): + def test(self): + huge = 1 << 40000 + mhuge = -huge + self.assertEqual(huge / huge, 1.0) + self.assertEqual(mhuge / mhuge, 1.0) + self.assertEqual(huge / mhuge, -1.0) + self.assertEqual(mhuge / huge, -1.0) + self.assertEqual(1 / huge, 0.0) + self.assertEqual(1 / huge, 0.0) + self.assertEqual(1 / mhuge, 0.0) + self.assertEqual(1 / mhuge, 0.0) + self.assertEqual((666 * huge + (huge >> 1)) / huge, 666.5) + self.assertEqual((666 * mhuge + (mhuge >> 1)) / mhuge, 666.5) + self.assertEqual((666 * huge + (huge >> 1)) / mhuge, -666.5) + self.assertEqual((666 * mhuge + (mhuge >> 1)) / huge, -666.5) + self.assertEqual(huge / (huge << 1), 0.5) + self.assertEqual((1000000 * huge) / huge, 1000000) + + namespace = {'huge': huge, 'mhuge': mhuge} + + for overflow in ["float(huge)", "float(mhuge)", + "huge / 1", "huge / 2", "huge / -1", "huge / -2", + "mhuge / 100", "mhuge / 200"]: + # XXX(cwinter) this test doesn't pass when converted to + # use assertRaises. + try: + eval(overflow, namespace) + self.fail("expected OverflowError from %r" % overflow) + except OverflowError: + pass + + for underflow in ["1 / huge", "2 / huge", "-1 / huge", "-2 / huge", + "100 / mhuge", "200 / mhuge"]: + result = eval(underflow, namespace) + self.assertEqual(result, 0.0, + "expected underflow to 0 from %r" % underflow) + + for zero in ["huge / 0", "mhuge / 0"]: + self.assertRaises(ZeroDivisionError, eval, zero, namespace) -test_true_division() + +def test_main(): + run_unittest(TrueDivisionTests) + +if __name__ == "__main__": + test_main() Modified: python/branches/p3yk/Lib/test/test_macpath.py ============================================================================== --- python/branches/p3yk/Lib/test/test_macpath.py (original) +++ python/branches/p3yk/Lib/test/test_macpath.py Fri Apr 27 21:54:29 2007 @@ -48,7 +48,7 @@ splitext = macpath.splitext self.assertEquals(splitext(":foo.ext"), (':foo', '.ext')) self.assertEquals(splitext("foo:foo.ext"), ('foo:foo', '.ext')) - self.assertEquals(splitext(".ext"), ('', '.ext')) + self.assertEquals(splitext(".ext"), ('.ext', '')) self.assertEquals(splitext("foo.ext:foo"), ('foo.ext:foo', '')) self.assertEquals(splitext(":foo.ext:"), (':foo.ext:', '')) self.assertEquals(splitext(""), ('', '')) Modified: python/branches/p3yk/Lib/test/test_mailbox.py ============================================================================== --- python/branches/p3yk/Lib/test/test_mailbox.py (original) +++ python/branches/p3yk/Lib/test/test_mailbox.py Fri Apr 27 21:54:29 2007 @@ -54,6 +54,7 @@ def setUp(self): self._path = test_support.TESTFN + self._delete_recursively(self._path) self._box = self._factory(self._path) def tearDown(self): @@ -686,7 +687,7 @@ self._box.close() self._delete_recursively(self._path) for lock_remnant in glob.glob(self._path + '.*'): - os.remove(lock_remnant) + test_support.unlink(lock_remnant) def test_add_from_string(self): # Add a string starting with 'From ' to the mailbox @@ -909,7 +910,7 @@ self._box.close() self._delete_recursively(self._path) for lock_remnant in glob.glob(self._path + '.*'): - os.remove(lock_remnant) + test_support.unlink(lock_remnant) def test_labels(self): # Get labels from the mailbox Modified: python/branches/p3yk/Lib/test/test_metaclass.py ============================================================================== --- python/branches/p3yk/Lib/test/test_metaclass.py (original) +++ python/branches/p3yk/Lib/test/test_metaclass.py Fri Apr 27 21:54:29 2007 @@ -63,6 +63,8 @@ ... def __new__(cls, name, bases, namespace, **kwds): ... print("New called:", kwds) ... return type.__new__(cls, name, bases, namespace) + ... def __init__(cls, *args, **kwds): + ... pass ... >>> class C(metaclass=M): ... def meth(self): print("Hello") Modified: python/branches/p3yk/Lib/test/test_minidom.py ============================================================================== --- python/branches/p3yk/Lib/test/test_minidom.py (original) +++ python/branches/p3yk/Lib/test/test_minidom.py Fri Apr 27 21:54:29 2007 @@ -5,7 +5,8 @@ import pickle import traceback from StringIO import StringIO -from test.test_support import verbose +from test.test_support import verbose, run_unittest, TestSkipped +import unittest import xml.dom import xml.dom.minidom @@ -22,680 +23,9 @@ tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml") del base -def confirm(test, testname = "Test"): - if not test: - print("Failed " + testname) - raise Exception - -def testParseFromFile(): - dom = parse(StringIO(open(tstfile).read())) - dom.unlink() - confirm(isinstance(dom,Document)) - -def testGetElementsByTagName(): - dom = parse(tstfile) - confirm(dom.getElementsByTagName("LI") == \ - dom.documentElement.getElementsByTagName("LI")) - dom.unlink() - -def testInsertBefore(): - dom = parseString("") - root = dom.documentElement - elem = root.childNodes[0] - nelem = dom.createElement("element") - root.insertBefore(nelem, elem) - confirm(len(root.childNodes) == 2 - and root.childNodes.length == 2 - and root.childNodes[0] is nelem - and root.childNodes.item(0) is nelem - and root.childNodes[1] is elem - and root.childNodes.item(1) is elem - and root.firstChild is nelem - and root.lastChild is elem - and root.toxml() == "" - , "testInsertBefore -- node properly placed in tree") - nelem = dom.createElement("element") - root.insertBefore(nelem, None) - confirm(len(root.childNodes) == 3 - and root.childNodes.length == 3 - and root.childNodes[1] is elem - and root.childNodes.item(1) is elem - and root.childNodes[2] is nelem - and root.childNodes.item(2) is nelem - and root.lastChild is nelem - and nelem.previousSibling is elem - and root.toxml() == "" - , "testInsertBefore -- node properly placed in tree") - nelem2 = dom.createElement("bar") - root.insertBefore(nelem2, nelem) - confirm(len(root.childNodes) == 4 - and root.childNodes.length == 4 - and root.childNodes[2] is nelem2 - and root.childNodes.item(2) is nelem2 - and root.childNodes[3] is nelem - and root.childNodes.item(3) is nelem - and nelem2.nextSibling is nelem - and nelem.previousSibling is nelem2 - and root.toxml() == "" - , "testInsertBefore -- node properly placed in tree") - dom.unlink() - -def _create_fragment_test_nodes(): - dom = parseString("") - orig = dom.createTextNode("original") - c1 = dom.createTextNode("foo") - c2 = dom.createTextNode("bar") - c3 = dom.createTextNode("bat") - dom.documentElement.appendChild(orig) - frag = dom.createDocumentFragment() - frag.appendChild(c1) - frag.appendChild(c2) - frag.appendChild(c3) - return dom, orig, c1, c2, c3, frag - -def testInsertBeforeFragment(): - dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() - dom.documentElement.insertBefore(frag, None) - confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), - "insertBefore(, None)") - frag.unlink() - dom.unlink() - # - dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() - dom.documentElement.insertBefore(frag, orig) - confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig), - "insertBefore(, orig)") - frag.unlink() - dom.unlink() - -def testAppendChild(): - dom = parse(tstfile) - dom.documentElement.appendChild(dom.createComment(u"Hello")) - confirm(dom.documentElement.childNodes[-1].nodeName == "#comment") - confirm(dom.documentElement.childNodes[-1].data == "Hello") - dom.unlink() - -def testAppendChildFragment(): - dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() - dom.documentElement.appendChild(frag) - confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), - "appendChild()") - frag.unlink() - dom.unlink() - -def testReplaceChildFragment(): - dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() - dom.documentElement.replaceChild(frag, orig) - orig.unlink() - confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3), - "replaceChild()") - frag.unlink() - dom.unlink() - -def testLegalChildren(): - dom = Document() - elem = dom.createElement('element') - text = dom.createTextNode('text') - - try: dom.appendChild(text) - except xml.dom.HierarchyRequestErr: pass - else: - print("dom.appendChild didn't raise HierarchyRequestErr") - - dom.appendChild(elem) - try: dom.insertBefore(text, elem) - except xml.dom.HierarchyRequestErr: pass - else: - print("dom.appendChild didn't raise HierarchyRequestErr") - - try: dom.replaceChild(text, elem) - except xml.dom.HierarchyRequestErr: pass - else: - print("dom.appendChild didn't raise HierarchyRequestErr") - - nodemap = elem.attributes - try: nodemap.setNamedItem(text) - except xml.dom.HierarchyRequestErr: pass - else: - print("NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr") - - try: nodemap.setNamedItemNS(text) - except xml.dom.HierarchyRequestErr: pass - else: - print("NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr") - - elem.appendChild(text) - dom.unlink() - -def testNamedNodeMapSetItem(): - dom = Document() - elem = dom.createElement('element') - attrs = elem.attributes - attrs["foo"] = "bar" - a = attrs.item(0) - confirm(a.ownerDocument is dom, - "NamedNodeMap.__setitem__() sets ownerDocument") - confirm(a.ownerElement is elem, - "NamedNodeMap.__setitem__() sets ownerElement") - confirm(a.value == "bar", - "NamedNodeMap.__setitem__() sets value") - confirm(a.nodeValue == "bar", - "NamedNodeMap.__setitem__() sets nodeValue") - elem.unlink() - dom.unlink() - -def testNonZero(): - dom = parse(tstfile) - confirm(dom)# should not be zero - dom.appendChild(dom.createComment("foo")) - confirm(not dom.childNodes[-1].childNodes) - dom.unlink() - -def testUnlink(): - dom = parse(tstfile) - dom.unlink() - -def testElement(): - dom = Document() - dom.appendChild(dom.createElement("abc")) - confirm(dom.documentElement) - dom.unlink() - -def testAAA(): - dom = parseString("") - el = dom.documentElement - el.setAttribute("spam", "jam2") - confirm(el.toxml() == '', "testAAA") - a = el.getAttributeNode("spam") - confirm(a.ownerDocument is dom, - "setAttribute() sets ownerDocument") - confirm(a.ownerElement is dom.documentElement, - "setAttribute() sets ownerElement") - dom.unlink() - -def testAAB(): - dom = parseString("") - el = dom.documentElement - el.setAttribute("spam", "jam") - el.setAttribute("spam", "jam2") - confirm(el.toxml() == '', "testAAB") - dom.unlink() - -def testAddAttr(): - dom = Document() - child = dom.appendChild(dom.createElement("abc")) - - child.setAttribute("def", "ghi") - confirm(child.getAttribute("def") == "ghi") - confirm(child.attributes["def"].value == "ghi") - - child.setAttribute("jkl", "mno") - confirm(child.getAttribute("jkl") == "mno") - confirm(child.attributes["jkl"].value == "mno") - - confirm(len(child.attributes) == 2) - - child.setAttribute("def", "newval") - confirm(child.getAttribute("def") == "newval") - confirm(child.attributes["def"].value == "newval") - - confirm(len(child.attributes) == 2) - dom.unlink() - -def testDeleteAttr(): - dom = Document() - child = dom.appendChild(dom.createElement("abc")) - - confirm(len(child.attributes) == 0) - child.setAttribute("def", "ghi") - confirm(len(child.attributes) == 1) - del child.attributes["def"] - confirm(len(child.attributes) == 0) - dom.unlink() - -def testRemoveAttr(): - dom = Document() - child = dom.appendChild(dom.createElement("abc")) - - child.setAttribute("def", "ghi") - confirm(len(child.attributes) == 1) - child.removeAttribute("def") - confirm(len(child.attributes) == 0) - - dom.unlink() - -def testRemoveAttrNS(): - dom = Document() - child = dom.appendChild( - dom.createElementNS("http://www.python.org", "python:abc")) - child.setAttributeNS("http://www.w3.org", "xmlns:python", - "http://www.python.org") - child.setAttributeNS("http://www.python.org", "python:abcattr", "foo") - confirm(len(child.attributes) == 2) - child.removeAttributeNS("http://www.python.org", "abcattr") - confirm(len(child.attributes) == 1) - - dom.unlink() - -def testRemoveAttributeNode(): - dom = Document() - child = dom.appendChild(dom.createElement("foo")) - child.setAttribute("spam", "jam") - confirm(len(child.attributes) == 1) - node = child.getAttributeNode("spam") - child.removeAttributeNode(node) - confirm(len(child.attributes) == 0 - and child.getAttributeNode("spam") is None) - - dom.unlink() - -def testChangeAttr(): - dom = parseString("") - el = dom.documentElement - el.setAttribute("spam", "jam") - confirm(len(el.attributes) == 1) - el.setAttribute("spam", "bam") - # Set this attribute to be an ID and make sure that doesn't change - # when changing the value: - el.setIdAttribute("spam") - confirm(len(el.attributes) == 1 - and el.attributes["spam"].value == "bam" - and el.attributes["spam"].nodeValue == "bam" - and el.getAttribute("spam") == "bam" - and el.getAttributeNode("spam").isId) - el.attributes["spam"] = "ham" - confirm(len(el.attributes) == 1 - and el.attributes["spam"].value == "ham" - and el.attributes["spam"].nodeValue == "ham" - and el.getAttribute("spam") == "ham" - and el.attributes["spam"].isId) - el.setAttribute("spam2", "bam") - confirm(len(el.attributes) == 2 - and el.attributes["spam"].value == "ham" - and el.attributes["spam"].nodeValue == "ham" - and el.getAttribute("spam") == "ham" - and el.attributes["spam2"].value == "bam" - and el.attributes["spam2"].nodeValue == "bam" - and el.getAttribute("spam2") == "bam") - el.attributes["spam2"] = "bam2" - confirm(len(el.attributes) == 2 - and el.attributes["spam"].value == "ham" - and el.attributes["spam"].nodeValue == "ham" - and el.getAttribute("spam") == "ham" - and el.attributes["spam2"].value == "bam2" - and el.attributes["spam2"].nodeValue == "bam2" - and el.getAttribute("spam2") == "bam2") - dom.unlink() - -def testGetAttrList(): - pass - -def testGetAttrValues(): pass - -def testGetAttrLength(): pass - -def testGetAttribute(): pass - -def testGetAttributeNS(): pass - -def testGetAttributeNode(): pass - -def testGetElementsByTagNameNS(): - d=""" - - """ - dom = parseString(d) - elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem") - confirm(len(elems) == 1 - and elems[0].namespaceURI == "http://pyxml.sf.net/minidom" - and elems[0].localName == "myelem" - and elems[0].prefix == "minidom" - and elems[0].tagName == "minidom:myelem" - and elems[0].nodeName == "minidom:myelem") - dom.unlink() - -def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc, nsuri, lname): - nodelist = doc.getElementsByTagNameNS(nsuri, lname) - confirm(len(nodelist) == 0) - -def testGetEmptyNodeListFromElementsByTagNameNS(): - doc = parseString('') - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, 'http://xml.python.org/namespaces/a', 'localname') - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, '*', 'splat') - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, 'http://xml.python.org/namespaces/a', '*') - - doc = parseString('') - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, "http://xml.python.org/splat", "not-there") - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, "*", "not-there") - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, "http://somewhere.else.net/not-there", "e") - -def testElementReprAndStr(): - dom = Document() - el = dom.appendChild(dom.createElement("abc")) - string1 = repr(el) - string2 = str(el) - confirm(string1 == string2) - dom.unlink() - -# commented out until Fredrick's fix is checked in -def _testElementReprAndStrUnicode(): - dom = Document() - el = dom.appendChild(dom.createElement(u"abc")) - string1 = repr(el) - string2 = str(el) - confirm(string1 == string2) - dom.unlink() - -# commented out until Fredrick's fix is checked in -def _testElementReprAndStrUnicodeNS(): - dom = Document() - el = dom.appendChild( - dom.createElementNS(u"http://www.slashdot.org", u"slash:abc")) - string1 = repr(el) - string2 = str(el) - confirm(string1 == string2) - confirm(string1.find("slash:abc") != -1) - dom.unlink() - -def testAttributeRepr(): - dom = Document() - el = dom.appendChild(dom.createElement(u"abc")) - node = el.setAttribute("abc", "def") - confirm(str(node) == repr(node)) - dom.unlink() - -def testTextNodeRepr(): pass - -def testWriteXML(): - str = '' - dom = parseString(str) - domstr = dom.toxml() - dom.unlink() - confirm(str == domstr) - -def testAltNewline(): - str = '\n\n' - dom = parseString(str) - domstr = dom.toprettyxml(newl="\r\n") - dom.unlink() - confirm(domstr == str.replace("\n", "\r\n")) - -def testProcessingInstruction(): - dom = parseString('') - pi = dom.documentElement.firstChild - confirm(pi.target == "mypi" - and pi.data == "data \t\n " - and pi.nodeName == "mypi" - and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE - and pi.attributes is None - and not pi.hasChildNodes() - and len(pi.childNodes) == 0 - and pi.firstChild is None - and pi.lastChild is None - and pi.localName is None - and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE) - -def testProcessingInstructionRepr(): pass - -def testTextRepr(): pass - -def testWriteText(): pass - -def testDocumentElement(): pass - -def testTooManyDocumentElements(): - doc = parseString("") - elem = doc.createElement("extra") - try: - doc.appendChild(elem) - except xml.dom.HierarchyRequestErr: - pass - else: - print("Failed to catch expected exception when" \ - " adding extra document element.") - elem.unlink() - doc.unlink() - -def testCreateElementNS(): pass - -def testCreateAttributeNS(): pass - -def testParse(): pass - -def testParseString(): pass - -def testComment(): pass - -def testAttrListItem(): pass - -def testAttrListItems(): pass - -def testAttrListItemNS(): pass - -def testAttrListKeys(): pass - -def testAttrListKeysNS(): pass - -def testRemoveNamedItem(): - doc = parseString("") - e = doc.documentElement - attrs = e.attributes - a1 = e.getAttributeNode("a") - a2 = attrs.removeNamedItem("a") - confirm(a1.isSameNode(a2)) - try: - attrs.removeNamedItem("a") - except xml.dom.NotFoundErr: - pass - -def testRemoveNamedItemNS(): - doc = parseString("") - e = doc.documentElement - attrs = e.attributes - a1 = e.getAttributeNodeNS("http://xml.python.org/", "b") - a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b") - confirm(a1.isSameNode(a2)) - try: - attrs.removeNamedItemNS("http://xml.python.org/", "b") - except xml.dom.NotFoundErr: - pass - -def testAttrListValues(): pass - -def testAttrListLength(): pass - -def testAttrList__getitem__(): pass - -def testAttrList__setitem__(): pass - -def testSetAttrValueandNodeValue(): pass - -def testParseElement(): pass - -def testParseAttributes(): pass - -def testParseElementNamespaces(): pass - -def testParseAttributeNamespaces(): pass - -def testParseProcessingInstructions(): pass - -def testChildNodes(): pass - -def testFirstChild(): pass - -def testHasChildNodes(): pass - -def testCloneElementShallow(): - dom, clone = _setupCloneElement(0) - confirm(len(clone.childNodes) == 0 - and clone.childNodes.length == 0 - and clone.parentNode is None - and clone.toxml() == '' - , "testCloneElementShallow") - dom.unlink() - -def testCloneElementDeep(): - dom, clone = _setupCloneElement(1) - confirm(len(clone.childNodes) == 1 - and clone.childNodes.length == 1 - and clone.parentNode is None - and clone.toxml() == '' - , "testCloneElementDeep") - dom.unlink() - -def _setupCloneElement(deep): - dom = parseString("") - root = dom.documentElement - clone = root.cloneNode(deep) - _testCloneElementCopiesAttributes( - root, clone, "testCloneElement" + (deep and "Deep" or "Shallow")) - # mutilate the original so shared data is detected - root.tagName = root.nodeName = "MODIFIED" - root.setAttribute("attr", "NEW VALUE") - root.setAttribute("added", "VALUE") - return dom, clone - -def _testCloneElementCopiesAttributes(e1, e2, test): - attrs1 = e1.attributes - attrs2 = e2.attributes - keys1 = sorted(attrs1.keys()) - keys2 = sorted(attrs2.keys()) - confirm(keys1 == keys2, "clone of element has same attribute keys") - for i in range(len(keys1)): - a1 = attrs1.item(i) - a2 = attrs2.item(i) - confirm(a1 is not a2 - and a1.value == a2.value - and a1.nodeValue == a2.nodeValue - and a1.namespaceURI == a2.namespaceURI - and a1.localName == a2.localName - , "clone of attribute node has proper attribute values") - confirm(a2.ownerElement is e2, - "clone of attribute node correctly owned") - -def testCloneDocumentShallow(): - doc = parseString("\n" - "" - "\n" - "]>\n" - "") - doc2 = doc.cloneNode(0) - confirm(doc2 is None, - "testCloneDocumentShallow:" - " shallow cloning of documents makes no sense!") - -def testCloneDocumentDeep(): - doc = parseString("\n" - "" - "\n" - "]>\n" - "") - doc2 = doc.cloneNode(1) - confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)), - "testCloneDocumentDeep: document objects not distinct") - confirm(len(doc.childNodes) == len(doc2.childNodes), - "testCloneDocumentDeep: wrong number of Document children") - confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE, - "testCloneDocumentDeep: documentElement not an ELEMENT_NODE") - confirm(doc2.documentElement.ownerDocument.isSameNode(doc2), - "testCloneDocumentDeep: documentElement owner is not new document") - confirm(not doc.documentElement.isSameNode(doc2.documentElement), - "testCloneDocumentDeep: documentElement should not be shared") - if doc.doctype is not None: - # check the doctype iff the original DOM maintained it - confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE, - "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE") - confirm(doc2.doctype.ownerDocument.isSameNode(doc2)) - confirm(not doc.doctype.isSameNode(doc2.doctype)) - -def testCloneDocumentTypeDeepOk(): - doctype = create_nonempty_doctype() - clone = doctype.cloneNode(1) - confirm(clone is not None - and clone.nodeName == doctype.nodeName - and clone.name == doctype.name - and clone.publicId == doctype.publicId - and clone.systemId == doctype.systemId - and len(clone.entities) == len(doctype.entities) - and clone.entities.item(len(clone.entities)) is None - and len(clone.notations) == len(doctype.notations) - and clone.notations.item(len(clone.notations)) is None - and len(clone.childNodes) == 0) - for i in range(len(doctype.entities)): - se = doctype.entities.item(i) - ce = clone.entities.item(i) - confirm((not se.isSameNode(ce)) - and (not ce.isSameNode(se)) - and ce.nodeName == se.nodeName - and ce.notationName == se.notationName - and ce.publicId == se.publicId - and ce.systemId == se.systemId - and ce.encoding == se.encoding - and ce.actualEncoding == se.actualEncoding - and ce.version == se.version) - for i in range(len(doctype.notations)): - sn = doctype.notations.item(i) - cn = clone.notations.item(i) - confirm((not sn.isSameNode(cn)) - and (not cn.isSameNode(sn)) - and cn.nodeName == sn.nodeName - and cn.publicId == sn.publicId - and cn.systemId == sn.systemId) - -def testCloneDocumentTypeDeepNotOk(): - doc = create_doc_with_doctype() - clone = doc.doctype.cloneNode(1) - confirm(clone is None, "testCloneDocumentTypeDeepNotOk") - -def testCloneDocumentTypeShallowOk(): - doctype = create_nonempty_doctype() - clone = doctype.cloneNode(0) - confirm(clone is not None - and clone.nodeName == doctype.nodeName - and clone.name == doctype.name - and clone.publicId == doctype.publicId - and clone.systemId == doctype.systemId - and len(clone.entities) == 0 - and clone.entities.item(0) is None - and len(clone.notations) == 0 - and clone.notations.item(0) is None - and len(clone.childNodes) == 0) - -def testCloneDocumentTypeShallowNotOk(): - doc = create_doc_with_doctype() - clone = doc.doctype.cloneNode(0) - confirm(clone is None, "testCloneDocumentTypeShallowNotOk") - -def check_import_document(deep, testName): - doc1 = parseString("") - doc2 = parseString("") - try: - doc1.importNode(doc2, deep) - except xml.dom.NotSupportedErr: - pass - else: - raise Exception(testName + - ": expected NotSupportedErr when importing a document") - -def testImportDocumentShallow(): - check_import_document(0, "testImportDocumentShallow") - -def testImportDocumentDeep(): - check_import_document(1, "testImportDocumentDeep") - # The tests of DocumentType importing use these helpers to construct # the documents to work with, since not all DOM builders actually # create the DocumentType nodes. - def create_doc_without_doctype(doctype=None): return getDOMImplementation().createDocument(None, "doc", doctype) @@ -722,673 +52,1263 @@ doctype.notations.item(0).ownerDocument = doc return doc -def testImportDocumentTypeShallow(): - src = create_doc_with_doctype() - target = create_doc_without_doctype() - try: - imported = target.importNode(src.doctype, 0) - except xml.dom.NotSupportedErr: - pass - else: - raise Exception( - "testImportDocumentTypeShallow: expected NotSupportedErr") - -def testImportDocumentTypeDeep(): - src = create_doc_with_doctype() - target = create_doc_without_doctype() - try: - imported = target.importNode(src.doctype, 1) - except xml.dom.NotSupportedErr: - pass - else: - raise Exception( - "testImportDocumentTypeDeep: expected NotSupportedErr") - -# Testing attribute clones uses a helper, and should always be deep, -# even if the argument to cloneNode is false. -def check_clone_attribute(deep, testName): - doc = parseString("") - attr = doc.documentElement.getAttributeNode("attr") - assert attr is not None - clone = attr.cloneNode(deep) - confirm(not clone.isSameNode(attr)) - confirm(not attr.isSameNode(clone)) - confirm(clone.ownerElement is None, - testName + ": ownerElement should be None") - confirm(clone.ownerDocument.isSameNode(attr.ownerDocument), - testName + ": ownerDocument does not match") - confirm(clone.specified, - testName + ": cloned attribute must have specified == True") - -def testCloneAttributeShallow(): - check_clone_attribute(0, "testCloneAttributeShallow") - -def testCloneAttributeDeep(): - check_clone_attribute(1, "testCloneAttributeDeep") - -def check_clone_pi(deep, testName): - doc = parseString("") - pi = doc.firstChild - assert pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE - clone = pi.cloneNode(deep) - confirm(clone.target == pi.target - and clone.data == pi.data) - -def testClonePIShallow(): - check_clone_pi(0, "testClonePIShallow") - -def testClonePIDeep(): - check_clone_pi(1, "testClonePIDeep") - -def testNormalize(): - doc = parseString("") - root = doc.documentElement - root.appendChild(doc.createTextNode("first")) - root.appendChild(doc.createTextNode("second")) - confirm(len(root.childNodes) == 2 - and root.childNodes.length == 2, "testNormalize -- preparation") - doc.normalize() - confirm(len(root.childNodes) == 1 - and root.childNodes.length == 1 - and root.firstChild is root.lastChild - and root.firstChild.data == "firstsecond" - , "testNormalize -- result") - doc.unlink() - - doc = parseString("") - root = doc.documentElement - root.appendChild(doc.createTextNode("")) - doc.normalize() - confirm(len(root.childNodes) == 0 - and root.childNodes.length == 0, - "testNormalize -- single empty node removed") - doc.unlink() - -def testSiblings(): - doc = parseString("text?") - root = doc.documentElement - (pi, text, elm) = root.childNodes - - confirm(pi.nextSibling is text and - pi.previousSibling is None and - text.nextSibling is elm and - text.previousSibling is pi and - elm.nextSibling is None and - elm.previousSibling is text, "testSiblings") - - doc.unlink() - -def testParents(): - doc = parseString("") - root = doc.documentElement - elm1 = root.childNodes[0] - (elm2a, elm2b) = elm1.childNodes - elm3 = elm2b.childNodes[0] - - confirm(root.parentNode is doc and - elm1.parentNode is root and - elm2a.parentNode is elm1 and - elm2b.parentNode is elm1 and - elm3.parentNode is elm2b, "testParents") - - doc.unlink() - -def testNodeListItem(): - doc = parseString("") - children = doc.childNodes - docelem = children[0] - confirm(children[0] is children.item(0) - and children.item(1) is None - and docelem.childNodes.item(0) is docelem.childNodes[0] - and docelem.childNodes.item(1) is docelem.childNodes[1] - and docelem.childNodes.item(0).childNodes.item(0) is None, - "test NodeList.item()") - doc.unlink() - -def testSAX2DOM(): - from xml.dom import pulldom - - sax2dom = pulldom.SAX2DOM() - sax2dom.startDocument() - sax2dom.startElement("doc", {}) - sax2dom.characters("text") - sax2dom.startElement("subelm", {}) - sax2dom.characters("text") - sax2dom.endElement("subelm") - sax2dom.characters("text") - sax2dom.endElement("doc") - sax2dom.endDocument() - - doc = sax2dom.document - root = doc.documentElement - (text1, elm1, text2) = root.childNodes - text3 = elm1.childNodes[0] - - confirm(text1.previousSibling is None and - text1.nextSibling is elm1 and - elm1.previousSibling is text1 and - elm1.nextSibling is text2 and - text2.previousSibling is elm1 and - text2.nextSibling is None and - text3.previousSibling is None and - text3.nextSibling is None, "testSAX2DOM - siblings") - - confirm(root.parentNode is doc and - text1.parentNode is root and - elm1.parentNode is root and - text2.parentNode is root and - text3.parentNode is elm1, "testSAX2DOM - parents") - - doc.unlink() - -def testEncodings(): - doc = parseString('') - confirm(doc.toxml() == u'\u20ac' - and doc.toxml('utf-8') == '\xe2\x82\xac' - and doc.toxml('iso-8859-15') == '\xa4', - "testEncodings - encoding EURO SIGN") - - # Verify that character decoding errors throw exceptions instead of crashing - try: - doc = parseString('Comment \xe7a va ? Tr\xe8s bien ?') - except UnicodeDecodeError: - pass - else: - print('parsing with bad encoding should raise a UnicodeDecodeError') +class MinidomTest(unittest.TestCase): + def tearDown(self): + try: + Node.allnodes + except AttributeError: + # We don't actually have the minidom from the standard library, + # but are picking up the PyXML version from site-packages. + pass + else: + self.confirm(len(Node.allnodes) == 0, + "assertion: len(Node.allnodes) == 0") + if len(Node.allnodes): + print("Garbage left over:") + if verbose: + print(list(Node.allnodes.items())[0:10]) + else: + # Don't print specific nodes if repeatable results + # are needed + print(len(Node.allnodes)) + Node.allnodes = {} + + def confirm(self, test, testname = "Test"): + self.assertTrue(test, testname) - doc.unlink() + def checkWholeText(self, node, s): + t = node.wholeText + self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t))) + + def testParseFromFile(self): + dom = parse(StringIO(open(tstfile).read())) + dom.unlink() + self.confirm(isinstance(dom, Document)) + + def testGetElementsByTagName(self): + dom = parse(tstfile) + self.confirm(dom.getElementsByTagName("LI") == \ + dom.documentElement.getElementsByTagName("LI")) + dom.unlink() + + def testInsertBefore(self): + dom = parseString("") + root = dom.documentElement + elem = root.childNodes[0] + nelem = dom.createElement("element") + root.insertBefore(nelem, elem) + self.confirm(len(root.childNodes) == 2 + and root.childNodes.length == 2 + and root.childNodes[0] is nelem + and root.childNodes.item(0) is nelem + and root.childNodes[1] is elem + and root.childNodes.item(1) is elem + and root.firstChild is nelem + and root.lastChild is elem + and root.toxml() == "" + , "testInsertBefore -- node properly placed in tree") + nelem = dom.createElement("element") + root.insertBefore(nelem, None) + self.confirm(len(root.childNodes) == 3 + and root.childNodes.length == 3 + and root.childNodes[1] is elem + and root.childNodes.item(1) is elem + and root.childNodes[2] is nelem + and root.childNodes.item(2) is nelem + and root.lastChild is nelem + and nelem.previousSibling is elem + and root.toxml() == "" + , "testInsertBefore -- node properly placed in tree") + nelem2 = dom.createElement("bar") + root.insertBefore(nelem2, nelem) + self.confirm(len(root.childNodes) == 4 + and root.childNodes.length == 4 + and root.childNodes[2] is nelem2 + and root.childNodes.item(2) is nelem2 + and root.childNodes[3] is nelem + and root.childNodes.item(3) is nelem + and nelem2.nextSibling is nelem + and nelem.previousSibling is nelem2 + and root.toxml() == + "" + , "testInsertBefore -- node properly placed in tree") + dom.unlink() + + def _create_fragment_test_nodes(self): + dom = parseString("") + orig = dom.createTextNode("original") + c1 = dom.createTextNode("foo") + c2 = dom.createTextNode("bar") + c3 = dom.createTextNode("bat") + dom.documentElement.appendChild(orig) + frag = dom.createDocumentFragment() + frag.appendChild(c1) + frag.appendChild(c2) + frag.appendChild(c3) + return dom, orig, c1, c2, c3, frag + + def testInsertBeforeFragment(self): + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.insertBefore(frag, None) + self.confirm(tuple(dom.documentElement.childNodes) == + (orig, c1, c2, c3), + "insertBefore(, None)") + frag.unlink() + dom.unlink() + + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.insertBefore(frag, orig) + self.confirm(tuple(dom.documentElement.childNodes) == + (c1, c2, c3, orig), + "insertBefore(, orig)") + frag.unlink() + dom.unlink() + + def testAppendChild(self): + dom = parse(tstfile) + dom.documentElement.appendChild(dom.createComment(u"Hello")) + self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment") + self.confirm(dom.documentElement.childNodes[-1].data == "Hello") + dom.unlink() + + def testAppendChildFragment(self): + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.appendChild(frag) + self.confirm(tuple(dom.documentElement.childNodes) == + (orig, c1, c2, c3), + "appendChild()") + frag.unlink() + dom.unlink() + + def testReplaceChildFragment(self): + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.replaceChild(frag, orig) + orig.unlink() + self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3), + "replaceChild()") + frag.unlink() + dom.unlink() + + def testLegalChildren(self): + dom = Document() + elem = dom.createElement('element') + text = dom.createTextNode('text') + self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text) + + dom.appendChild(elem) + self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text, + elem) + self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text, + elem) + + nodemap = elem.attributes + self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem, + text) + self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS, + text) + + elem.appendChild(text) + dom.unlink() + + def testNamedNodeMapSetItem(self): + dom = Document() + elem = dom.createElement('element') + attrs = elem.attributes + attrs["foo"] = "bar" + a = attrs.item(0) + self.confirm(a.ownerDocument is dom, + "NamedNodeMap.__setitem__() sets ownerDocument") + self.confirm(a.ownerElement is elem, + "NamedNodeMap.__setitem__() sets ownerElement") + self.confirm(a.value == "bar", + "NamedNodeMap.__setitem__() sets value") + self.confirm(a.nodeValue == "bar", + "NamedNodeMap.__setitem__() sets nodeValue") + elem.unlink() + dom.unlink() + + def testNonZero(self): + dom = parse(tstfile) + self.confirm(dom)# should not be zero + dom.appendChild(dom.createComment("foo")) + self.confirm(not dom.childNodes[-1].childNodes) + dom.unlink() + + def testUnlink(self): + dom = parse(tstfile) + dom.unlink() + + def testElement(self): + dom = Document() + dom.appendChild(dom.createElement("abc")) + self.confirm(dom.documentElement) + dom.unlink() + + def testAAA(self): + dom = parseString("") + el = dom.documentElement + el.setAttribute("spam", "jam2") + self.confirm(el.toxml() == '', "testAAA") + a = el.getAttributeNode("spam") + self.confirm(a.ownerDocument is dom, + "setAttribute() sets ownerDocument") + self.confirm(a.ownerElement is dom.documentElement, + "setAttribute() sets ownerElement") + dom.unlink() + + def testAAB(self): + dom = parseString("") + el = dom.documentElement + el.setAttribute("spam", "jam") + el.setAttribute("spam", "jam2") + self.confirm(el.toxml() == '', "testAAB") + dom.unlink() + + def testAddAttr(self): + dom = Document() + child = dom.appendChild(dom.createElement("abc")) + + child.setAttribute("def", "ghi") + self.confirm(child.getAttribute("def") == "ghi") + self.confirm(child.attributes["def"].value == "ghi") + + child.setAttribute("jkl", "mno") + self.confirm(child.getAttribute("jkl") == "mno") + self.confirm(child.attributes["jkl"].value == "mno") + + self.confirm(len(child.attributes) == 2) + + child.setAttribute("def", "newval") + self.confirm(child.getAttribute("def") == "newval") + self.confirm(child.attributes["def"].value == "newval") + + self.confirm(len(child.attributes) == 2) + dom.unlink() + + def testDeleteAttr(self): + dom = Document() + child = dom.appendChild(dom.createElement("abc")) + + self.confirm(len(child.attributes) == 0) + child.setAttribute("def", "ghi") + self.confirm(len(child.attributes) == 1) + del child.attributes["def"] + self.confirm(len(child.attributes) == 0) + dom.unlink() + + def testRemoveAttr(self): + dom = Document() + child = dom.appendChild(dom.createElement("abc")) + + child.setAttribute("def", "ghi") + self.confirm(len(child.attributes) == 1) + child.removeAttribute("def") + self.confirm(len(child.attributes) == 0) + dom.unlink() + + def testRemoveAttrNS(self): + dom = Document() + child = dom.appendChild( + dom.createElementNS("http://www.python.org", "python:abc")) + child.setAttributeNS("http://www.w3.org", "xmlns:python", + "http://www.python.org") + child.setAttributeNS("http://www.python.org", "python:abcattr", "foo") + self.confirm(len(child.attributes) == 2) + child.removeAttributeNS("http://www.python.org", "abcattr") + self.confirm(len(child.attributes) == 1) + dom.unlink() + + def testRemoveAttributeNode(self): + dom = Document() + child = dom.appendChild(dom.createElement("foo")) + child.setAttribute("spam", "jam") + self.confirm(len(child.attributes) == 1) + node = child.getAttributeNode("spam") + child.removeAttributeNode(node) + self.confirm(len(child.attributes) == 0 + and child.getAttributeNode("spam") is None) + dom.unlink() + + def testChangeAttr(self): + dom = parseString("") + el = dom.documentElement + el.setAttribute("spam", "jam") + self.confirm(len(el.attributes) == 1) + el.setAttribute("spam", "bam") + # Set this attribute to be an ID and make sure that doesn't change + # when changing the value: + el.setIdAttribute("spam") + self.confirm(len(el.attributes) == 1 + and el.attributes["spam"].value == "bam" + and el.attributes["spam"].nodeValue == "bam" + and el.getAttribute("spam") == "bam" + and el.getAttributeNode("spam").isId) + el.attributes["spam"] = "ham" + self.confirm(len(el.attributes) == 1 + and el.attributes["spam"].value == "ham" + and el.attributes["spam"].nodeValue == "ham" + and el.getAttribute("spam") == "ham" + and el.attributes["spam"].isId) + el.setAttribute("spam2", "bam") + self.confirm(len(el.attributes) == 2 + and el.attributes["spam"].value == "ham" + and el.attributes["spam"].nodeValue == "ham" + and el.getAttribute("spam") == "ham" + and el.attributes["spam2"].value == "bam" + and el.attributes["spam2"].nodeValue == "bam" + and el.getAttribute("spam2") == "bam") + el.attributes["spam2"] = "bam2" + self.confirm(len(el.attributes) == 2 + and el.attributes["spam"].value == "ham" + and el.attributes["spam"].nodeValue == "ham" + and el.getAttribute("spam") == "ham" + and el.attributes["spam2"].value == "bam2" + and el.attributes["spam2"].nodeValue == "bam2" + and el.getAttribute("spam2") == "bam2") + dom.unlink() -class UserDataHandler: - called = 0 - def handle(self, operation, key, data, src, dst): - dst.setUserData(key, data + 1, self) - src.setUserData(key, None, None) - self.called = 1 - -def testUserData(): - dom = Document() - n = dom.createElement('e') - confirm(n.getUserData("foo") is None) - n.setUserData("foo", None, None) - confirm(n.getUserData("foo") is None) - n.setUserData("foo", 12, 12) - n.setUserData("bar", 13, 13) - confirm(n.getUserData("foo") == 12) - confirm(n.getUserData("bar") == 13) - n.setUserData("foo", None, None) - confirm(n.getUserData("foo") is None) - confirm(n.getUserData("bar") == 13) - - handler = UserDataHandler() - n.setUserData("bar", 12, handler) - c = n.cloneNode(1) - confirm(handler.called - and n.getUserData("bar") is None - and c.getUserData("bar") == 13) - n.unlink() - c.unlink() - dom.unlink() - -def testRenameAttribute(): - doc = parseString("") - elem = doc.documentElement - attrmap = elem.attributes - attr = elem.attributes['a'] - - # Simple renaming - attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b") - confirm(attr.name == "b" - and attr.nodeName == "b" - and attr.localName is None - and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE - and attr.prefix is None - and attr.value == "v" - and elem.getAttributeNode("a") is None - and elem.getAttributeNode("b").isSameNode(attr) - and attrmap["b"].isSameNode(attr) - and attr.ownerDocument.isSameNode(doc) - and attr.ownerElement.isSameNode(elem)) - - # Rename to have a namespace, no prefix - attr = doc.renameNode(attr, "http://xml.python.org/ns", "c") - confirm(attr.name == "c" - and attr.nodeName == "c" - and attr.localName == "c" - and attr.namespaceURI == "http://xml.python.org/ns" - and attr.prefix is None - and attr.value == "v" - and elem.getAttributeNode("a") is None - and elem.getAttributeNode("b") is None - and elem.getAttributeNode("c").isSameNode(attr) - and elem.getAttributeNodeNS( - "http://xml.python.org/ns", "c").isSameNode(attr) - and attrmap["c"].isSameNode(attr) - and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr)) - - # Rename to have a namespace, with prefix - attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d") - confirm(attr.name == "p:d" - and attr.nodeName == "p:d" - and attr.localName == "d" - and attr.namespaceURI == "http://xml.python.org/ns2" - and attr.prefix == "p" - and attr.value == "v" - and elem.getAttributeNode("a") is None - and elem.getAttributeNode("b") is None - and elem.getAttributeNode("c") is None - and elem.getAttributeNodeNS( - "http://xml.python.org/ns", "c") is None - and elem.getAttributeNode("p:d").isSameNode(attr) - and elem.getAttributeNodeNS( - "http://xml.python.org/ns2", "d").isSameNode(attr) - and attrmap["p:d"].isSameNode(attr) - and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr)) - - # Rename back to a simple non-NS node - attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e") - confirm(attr.name == "e" - and attr.nodeName == "e" - and attr.localName is None - and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE - and attr.prefix is None - and attr.value == "v" - and elem.getAttributeNode("a") is None - and elem.getAttributeNode("b") is None - and elem.getAttributeNode("c") is None - and elem.getAttributeNode("p:d") is None - and elem.getAttributeNodeNS( - "http://xml.python.org/ns", "c") is None - and elem.getAttributeNode("e").isSameNode(attr) - and attrmap["e"].isSameNode(attr)) - - try: - doc.renameNode(attr, "http://xml.python.org/ns", "xmlns") - except xml.dom.NamespaceErr: + def testGetAttrList(self): pass - else: - print("expected NamespaceErr") - checkRenameNodeSharedConstraints(doc, attr) - doc.unlink() + def testGetAttrValues(self): pass -def testRenameElement(): - doc = parseString("") - elem = doc.documentElement - - # Simple renaming - elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a") - confirm(elem.tagName == "a" - and elem.nodeName == "a" - and elem.localName is None - and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE - and elem.prefix is None - and elem.ownerDocument.isSameNode(doc)) - - # Rename to have a namespace, no prefix - elem = doc.renameNode(elem, "http://xml.python.org/ns", "b") - confirm(elem.tagName == "b" - and elem.nodeName == "b" - and elem.localName == "b" - and elem.namespaceURI == "http://xml.python.org/ns" - and elem.prefix is None - and elem.ownerDocument.isSameNode(doc)) - - # Rename to have a namespace, with prefix - elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c") - confirm(elem.tagName == "p:c" - and elem.nodeName == "p:c" - and elem.localName == "c" - and elem.namespaceURI == "http://xml.python.org/ns2" - and elem.prefix == "p" - and elem.ownerDocument.isSameNode(doc)) - - # Rename back to a simple non-NS node - elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d") - confirm(elem.tagName == "d" - and elem.nodeName == "d" - and elem.localName is None - and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE - and elem.prefix is None - and elem.ownerDocument.isSameNode(doc)) - - checkRenameNodeSharedConstraints(doc, elem) - doc.unlink() - -def checkRenameNodeSharedConstraints(doc, node): - # Make sure illegal NS usage is detected: - try: - doc.renameNode(node, "http://xml.python.org/ns", "xmlns:foo") - except xml.dom.NamespaceErr: - pass - else: - print("expected NamespaceErr") + def testGetAttrLength(self): pass - doc2 = parseString("") - try: - doc2.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo") - except xml.dom.WrongDocumentErr: - pass - else: - print("expected WrongDocumentErr") + def testGetAttribute(self): pass -def testRenameOther(): - # We have to create a comment node explicitly since not all DOM - # builders used with minidom add comments to the DOM. - doc = xml.dom.minidom.getDOMImplementation().createDocument( - xml.dom.EMPTY_NAMESPACE, "e", None) - node = doc.createComment("comment") - try: - doc.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo") - except xml.dom.NotSupportedErr: - pass - else: - print("expected NotSupportedErr when renaming comment node") - doc.unlink() - -def checkWholeText(node, s): - t = node.wholeText - confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t))) - -def testWholeText(): - doc = parseString("a") - elem = doc.documentElement - text = elem.childNodes[0] - assert text.nodeType == Node.TEXT_NODE - - checkWholeText(text, "a") - elem.appendChild(doc.createTextNode("b")) - checkWholeText(text, "ab") - elem.insertBefore(doc.createCDATASection("c"), text) - checkWholeText(text, "cab") - - # make sure we don't cross other nodes - splitter = doc.createComment("comment") - elem.appendChild(splitter) - text2 = doc.createTextNode("d") - elem.appendChild(text2) - checkWholeText(text, "cab") - checkWholeText(text2, "d") - - x = doc.createElement("x") - elem.replaceChild(x, splitter) - splitter = x - checkWholeText(text, "cab") - checkWholeText(text2, "d") - - x = doc.createProcessingInstruction("y", "z") - elem.replaceChild(x, splitter) - splitter = x - checkWholeText(text, "cab") - checkWholeText(text2, "d") - - elem.removeChild(splitter) - checkWholeText(text, "cabd") - checkWholeText(text2, "cabd") - -def testPatch1094164 (): - doc = parseString("") - elem = doc.documentElement - e = elem.firstChild - confirm(e.parentNode is elem, "Before replaceChild()") - # Check that replacing a child with itself leaves the tree unchanged - elem.replaceChild(e, e) - confirm(e.parentNode is elem, "After replaceChild()") + def testGetAttributeNS(self): pass + def testGetAttributeNode(self): pass + + def testGetElementsByTagNameNS(self): + d=""" + + """ + dom = parseString(d) + elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", + "myelem") + self.confirm(len(elems) == 1 + and elems[0].namespaceURI == "http://pyxml.sf.net/minidom" + and elems[0].localName == "myelem" + and elems[0].prefix == "minidom" + and elems[0].tagName == "minidom:myelem" + and elems[0].nodeName == "minidom:myelem") + dom.unlink() + + def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri, + lname): + nodelist = doc.getElementsByTagNameNS(nsuri, lname) + self.confirm(len(nodelist) == 0) + + def testGetEmptyNodeListFromElementsByTagNameNS(self): + doc = parseString('') + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, 'http://xml.python.org/namespaces/a', 'localname') + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, '*', 'splat') + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, 'http://xml.python.org/namespaces/a', '*') + + doc = parseString('') + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, "http://xml.python.org/splat", "not-there") + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, "*", "not-there") + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, "http://somewhere.else.net/not-there", "e") + + def testElementReprAndStr(self): + dom = Document() + el = dom.appendChild(dom.createElement("abc")) + string1 = repr(el) + string2 = str(el) + self.confirm(string1 == string2) + dom.unlink() + + def testElementReprAndStrUnicode(self): + dom = Document() + el = dom.appendChild(dom.createElement(u"abc")) + string1 = repr(el) + string2 = str(el) + self.confirm(string1 == string2) + dom.unlink() + + def testElementReprAndStrUnicodeNS(self): + dom = Document() + el = dom.appendChild( + dom.createElementNS(u"http://www.slashdot.org", u"slash:abc")) + string1 = repr(el) + string2 = str(el) + self.confirm(string1 == string2) + self.confirm(string1.find("slash:abc") != -1) + dom.unlink() + + def testAttributeRepr(self): + dom = Document() + el = dom.appendChild(dom.createElement(u"abc")) + node = el.setAttribute("abc", "def") + self.confirm(str(node) == repr(node)) + dom.unlink() + + def testTextNodeRepr(self): pass + + def testWriteXML(self): + str = '' + dom = parseString(str) + domstr = dom.toxml() + dom.unlink() + self.confirm(str == domstr) + + def testAltNewline(self): + str = '\n\n' + dom = parseString(str) + domstr = dom.toprettyxml(newl="\r\n") + dom.unlink() + self.confirm(domstr == str.replace("\n", "\r\n")) + + def testProcessingInstruction(self): + dom = parseString('') + pi = dom.documentElement.firstChild + self.confirm(pi.target == "mypi" + and pi.data == "data \t\n " + and pi.nodeName == "mypi" + and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE + and pi.attributes is None + and not pi.hasChildNodes() + and len(pi.childNodes) == 0 + and pi.firstChild is None + and pi.lastChild is None + and pi.localName is None + and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE) + + def testProcessingInstructionRepr(self): pass + + def testTextRepr(self): pass + + def testWriteText(self): pass + + def testDocumentElement(self): pass + + def testTooManyDocumentElements(self): + doc = parseString("") + elem = doc.createElement("extra") + # Should raise an exception when adding an extra document element. + self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem) + elem.unlink() + doc.unlink() + + def testCreateElementNS(self): pass + + def testCreateAttributeNS(self): pass + + def testParse(self): pass + + def testParseString(self): pass + + def testComment(self): pass + + def testAttrListItem(self): pass + + def testAttrListItems(self): pass + + def testAttrListItemNS(self): pass + + def testAttrListKeys(self): pass + + def testAttrListKeysNS(self): pass + + def testRemoveNamedItem(self): + doc = parseString("") + e = doc.documentElement + attrs = e.attributes + a1 = e.getAttributeNode("a") + a2 = attrs.removeNamedItem("a") + self.confirm(a1.isSameNode(a2)) + self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a") + + def testRemoveNamedItemNS(self): + doc = parseString("") + e = doc.documentElement + attrs = e.attributes + a1 = e.getAttributeNodeNS("http://xml.python.org/", "b") + a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b") + self.confirm(a1.isSameNode(a2)) + self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS, + "http://xml.python.org/", "b") + + def testAttrListValues(self): pass + + def testAttrListLength(self): pass + + def testAttrList__getitem__(self): pass + + def testAttrList__setitem__(self): pass + + def testSetAttrValueandNodeValue(self): pass + + def testParseElement(self): pass + + def testParseAttributes(self): pass + + def testParseElementNamespaces(self): pass + + def testParseAttributeNamespaces(self): pass + + def testParseProcessingInstructions(self): pass + + def testChildNodes(self): pass + + def testFirstChild(self): pass + + def testHasChildNodes(self): pass + + def _testCloneElementCopiesAttributes(self, e1, e2, test): + attrs1 = e1.attributes + attrs2 = e2.attributes + keys1 = list(attrs1.keys()) + keys2 = list(attrs2.keys()) + keys1.sort() + keys2.sort() + self.confirm(keys1 == keys2, "clone of element has same attribute keys") + for i in range(len(keys1)): + a1 = attrs1.item(i) + a2 = attrs2.item(i) + self.confirm(a1 is not a2 + and a1.value == a2.value + and a1.nodeValue == a2.nodeValue + and a1.namespaceURI == a2.namespaceURI + and a1.localName == a2.localName + , "clone of attribute node has proper attribute values") + self.confirm(a2.ownerElement is e2, + "clone of attribute node correctly owned") + + def _setupCloneElement(self, deep): + dom = parseString("") + root = dom.documentElement + clone = root.cloneNode(deep) + self._testCloneElementCopiesAttributes( + root, clone, "testCloneElement" + (deep and "Deep" or "Shallow")) + # mutilate the original so shared data is detected + root.tagName = root.nodeName = "MODIFIED" + root.setAttribute("attr", "NEW VALUE") + root.setAttribute("added", "VALUE") + return dom, clone + + def testCloneElementShallow(self): + dom, clone = self._setupCloneElement(0) + self.confirm(len(clone.childNodes) == 0 + and clone.childNodes.length == 0 + and clone.parentNode is None + and clone.toxml() == '' + , "testCloneElementShallow") + dom.unlink() + + def testCloneElementDeep(self): + dom, clone = self._setupCloneElement(1) + self.confirm(len(clone.childNodes) == 1 + and clone.childNodes.length == 1 + and clone.parentNode is None + and clone.toxml() == '' + , "testCloneElementDeep") + dom.unlink() + + def testCloneDocumentShallow(self): + doc = parseString("\n" + "" + "\n" + "]>\n" + "") + doc2 = doc.cloneNode(0) + self.confirm(doc2 is None, + "testCloneDocumentShallow:" + " shallow cloning of documents makes no sense!") + + def testCloneDocumentDeep(self): + doc = parseString("\n" + "" + "\n" + "]>\n" + "") + doc2 = doc.cloneNode(1) + self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)), + "testCloneDocumentDeep: document objects not distinct") + self.confirm(len(doc.childNodes) == len(doc2.childNodes), + "testCloneDocumentDeep: wrong number of Document children") + self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE, + "testCloneDocumentDeep: documentElement not an ELEMENT_NODE") + self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2), + "testCloneDocumentDeep: documentElement owner is not new document") + self.confirm(not doc.documentElement.isSameNode(doc2.documentElement), + "testCloneDocumentDeep: documentElement should not be shared") + if doc.doctype is not None: + # check the doctype iff the original DOM maintained it + self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE, + "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE") + self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2)) + self.confirm(not doc.doctype.isSameNode(doc2.doctype)) + + def testCloneDocumentTypeDeepOk(self): + doctype = create_nonempty_doctype() + clone = doctype.cloneNode(1) + self.confirm(clone is not None + and clone.nodeName == doctype.nodeName + and clone.name == doctype.name + and clone.publicId == doctype.publicId + and clone.systemId == doctype.systemId + and len(clone.entities) == len(doctype.entities) + and clone.entities.item(len(clone.entities)) is None + and len(clone.notations) == len(doctype.notations) + and clone.notations.item(len(clone.notations)) is None + and len(clone.childNodes) == 0) + for i in range(len(doctype.entities)): + se = doctype.entities.item(i) + ce = clone.entities.item(i) + self.confirm((not se.isSameNode(ce)) + and (not ce.isSameNode(se)) + and ce.nodeName == se.nodeName + and ce.notationName == se.notationName + and ce.publicId == se.publicId + and ce.systemId == se.systemId + and ce.encoding == se.encoding + and ce.actualEncoding == se.actualEncoding + and ce.version == se.version) + for i in range(len(doctype.notations)): + sn = doctype.notations.item(i) + cn = clone.notations.item(i) + self.confirm((not sn.isSameNode(cn)) + and (not cn.isSameNode(sn)) + and cn.nodeName == sn.nodeName + and cn.publicId == sn.publicId + and cn.systemId == sn.systemId) + + def testCloneDocumentTypeDeepNotOk(self): + doc = create_doc_with_doctype() + clone = doc.doctype.cloneNode(1) + self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk") + + def testCloneDocumentTypeShallowOk(self): + doctype = create_nonempty_doctype() + clone = doctype.cloneNode(0) + self.confirm(clone is not None + and clone.nodeName == doctype.nodeName + and clone.name == doctype.name + and clone.publicId == doctype.publicId + and clone.systemId == doctype.systemId + and len(clone.entities) == 0 + and clone.entities.item(0) is None + and len(clone.notations) == 0 + and clone.notations.item(0) is None + and len(clone.childNodes) == 0) + + def testCloneDocumentTypeShallowNotOk(self): + doc = create_doc_with_doctype() + clone = doc.doctype.cloneNode(0) + self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk") + + def check_import_document(self, deep, testName): + doc1 = parseString("") + doc2 = parseString("") + self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep) + + def testImportDocumentShallow(self): + self.check_import_document(0, "testImportDocumentShallow") + + def testImportDocumentDeep(self): + self.check_import_document(1, "testImportDocumentDeep") + + def testImportDocumentTypeShallow(self): + src = create_doc_with_doctype() + target = create_doc_without_doctype() + self.assertRaises(xml.dom.NotSupportedErr, target.importNode, + src.doctype, 0) + + def testImportDocumentTypeDeep(self): + src = create_doc_with_doctype() + target = create_doc_without_doctype() + self.assertRaises(xml.dom.NotSupportedErr, target.importNode, + src.doctype, 1) + + # Testing attribute clones uses a helper, and should always be deep, + # even if the argument to cloneNode is false. + def check_clone_attribute(self, deep, testName): + doc = parseString("") + attr = doc.documentElement.getAttributeNode("attr") + self.failIfEqual(attr, None) + clone = attr.cloneNode(deep) + self.confirm(not clone.isSameNode(attr)) + self.confirm(not attr.isSameNode(clone)) + self.confirm(clone.ownerElement is None, + testName + ": ownerElement should be None") + self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument), + testName + ": ownerDocument does not match") + self.confirm(clone.specified, + testName + ": cloned attribute must have specified == True") + + def testCloneAttributeShallow(self): + self.check_clone_attribute(0, "testCloneAttributeShallow") + + def testCloneAttributeDeep(self): + self.check_clone_attribute(1, "testCloneAttributeDeep") + + def check_clone_pi(self, deep, testName): + doc = parseString("") + pi = doc.firstChild + self.assertEquals(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE) + clone = pi.cloneNode(deep) + self.confirm(clone.target == pi.target + and clone.data == pi.data) + + def testClonePIShallow(self): + self.check_clone_pi(0, "testClonePIShallow") + + def testClonePIDeep(self): + self.check_clone_pi(1, "testClonePIDeep") + + def testNormalize(self): + doc = parseString("") + root = doc.documentElement + root.appendChild(doc.createTextNode("first")) + root.appendChild(doc.createTextNode("second")) + self.confirm(len(root.childNodes) == 2 + and root.childNodes.length == 2, + "testNormalize -- preparation") + doc.normalize() + self.confirm(len(root.childNodes) == 1 + and root.childNodes.length == 1 + and root.firstChild is root.lastChild + and root.firstChild.data == "firstsecond" + , "testNormalize -- result") + doc.unlink() + + doc = parseString("") + root = doc.documentElement + root.appendChild(doc.createTextNode("")) + doc.normalize() + self.confirm(len(root.childNodes) == 0 + and root.childNodes.length == 0, + "testNormalize -- single empty node removed") + doc.unlink() + + def testSiblings(self): + doc = parseString("text?") + root = doc.documentElement + (pi, text, elm) = root.childNodes + + self.confirm(pi.nextSibling is text and + pi.previousSibling is None and + text.nextSibling is elm and + text.previousSibling is pi and + elm.nextSibling is None and + elm.previousSibling is text, "testSiblings") + + doc.unlink() + + def testParents(self): + doc = parseString( + "") + root = doc.documentElement + elm1 = root.childNodes[0] + (elm2a, elm2b) = elm1.childNodes + elm3 = elm2b.childNodes[0] + + self.confirm(root.parentNode is doc and + elm1.parentNode is root and + elm2a.parentNode is elm1 and + elm2b.parentNode is elm1 and + elm3.parentNode is elm2b, "testParents") + doc.unlink() + + def testNodeListItem(self): + doc = parseString("") + children = doc.childNodes + docelem = children[0] + self.confirm(children[0] is children.item(0) + and children.item(1) is None + and docelem.childNodes.item(0) is docelem.childNodes[0] + and docelem.childNodes.item(1) is docelem.childNodes[1] + and docelem.childNodes.item(0).childNodes.item(0) is None, + "test NodeList.item()") + doc.unlink() + + def testSAX2DOM(self): + from xml.dom import pulldom + + sax2dom = pulldom.SAX2DOM() + sax2dom.startDocument() + sax2dom.startElement("doc", {}) + sax2dom.characters("text") + sax2dom.startElement("subelm", {}) + sax2dom.characters("text") + sax2dom.endElement("subelm") + sax2dom.characters("text") + sax2dom.endElement("doc") + sax2dom.endDocument() + + doc = sax2dom.document + root = doc.documentElement + (text1, elm1, text2) = root.childNodes + text3 = elm1.childNodes[0] + + self.confirm(text1.previousSibling is None and + text1.nextSibling is elm1 and + elm1.previousSibling is text1 and + elm1.nextSibling is text2 and + text2.previousSibling is elm1 and + text2.nextSibling is None and + text3.previousSibling is None and + text3.nextSibling is None, "testSAX2DOM - siblings") + + self.confirm(root.parentNode is doc and + text1.parentNode is root and + elm1.parentNode is root and + text2.parentNode is root and + text3.parentNode is elm1, "testSAX2DOM - parents") + doc.unlink() + + def testEncodings(self): + doc = parseString('') + self.confirm(doc.toxml() == u'\u20ac' + and doc.toxml('utf-8') == + '\xe2\x82\xac' + and doc.toxml('iso-8859-15') == + '\xa4', + "testEncodings - encoding EURO SIGN") + + # Verify that character decoding errors throw exceptions instead + # of crashing + self.assertRaises(UnicodeDecodeError, parseString, + 'Comment \xe7a va ? Tr\xe8s bien ?') + + doc.unlink() + + class UserDataHandler: + called = 0 + def handle(self, operation, key, data, src, dst): + dst.setUserData(key, data + 1, self) + src.setUserData(key, None, None) + self.called = 1 + + def testUserData(self): + dom = Document() + n = dom.createElement('e') + self.confirm(n.getUserData("foo") is None) + n.setUserData("foo", None, None) + self.confirm(n.getUserData("foo") is None) + n.setUserData("foo", 12, 12) + n.setUserData("bar", 13, 13) + self.confirm(n.getUserData("foo") == 12) + self.confirm(n.getUserData("bar") == 13) + n.setUserData("foo", None, None) + self.confirm(n.getUserData("foo") is None) + self.confirm(n.getUserData("bar") == 13) + + handler = self.UserDataHandler() + n.setUserData("bar", 12, handler) + c = n.cloneNode(1) + self.confirm(handler.called + and n.getUserData("bar") is None + and c.getUserData("bar") == 13) + n.unlink() + c.unlink() + dom.unlink() + + def checkRenameNodeSharedConstraints(self, doc, node): + # Make sure illegal NS usage is detected: + self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node, + "http://xml.python.org/ns", "xmlns:foo") + doc2 = parseString("") + self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node, + xml.dom.EMPTY_NAMESPACE, "foo") + def testRenameAttribute(self): + doc = parseString("") + elem = doc.documentElement + attrmap = elem.attributes + attr = elem.attributes['a'] -def testReplaceWholeText(): - def setup(): - doc = parseString("ad") + # Simple renaming + attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b") + self.confirm(attr.name == "b" + and attr.nodeName == "b" + and attr.localName is None + and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE + and attr.prefix is None + and attr.value == "v" + and elem.getAttributeNode("a") is None + and elem.getAttributeNode("b").isSameNode(attr) + and attrmap["b"].isSameNode(attr) + and attr.ownerDocument.isSameNode(doc) + and attr.ownerElement.isSameNode(elem)) + + # Rename to have a namespace, no prefix + attr = doc.renameNode(attr, "http://xml.python.org/ns", "c") + self.confirm(attr.name == "c" + and attr.nodeName == "c" + and attr.localName == "c" + and attr.namespaceURI == "http://xml.python.org/ns" + and attr.prefix is None + and attr.value == "v" + and elem.getAttributeNode("a") is None + and elem.getAttributeNode("b") is None + and elem.getAttributeNode("c").isSameNode(attr) + and elem.getAttributeNodeNS( + "http://xml.python.org/ns", "c").isSameNode(attr) + and attrmap["c"].isSameNode(attr) + and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr)) + + # Rename to have a namespace, with prefix + attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d") + self.confirm(attr.name == "p:d" + and attr.nodeName == "p:d" + and attr.localName == "d" + and attr.namespaceURI == "http://xml.python.org/ns2" + and attr.prefix == "p" + and attr.value == "v" + and elem.getAttributeNode("a") is None + and elem.getAttributeNode("b") is None + and elem.getAttributeNode("c") is None + and elem.getAttributeNodeNS( + "http://xml.python.org/ns", "c") is None + and elem.getAttributeNode("p:d").isSameNode(attr) + and elem.getAttributeNodeNS( + "http://xml.python.org/ns2", "d").isSameNode(attr) + and attrmap["p:d"].isSameNode(attr) + and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr)) + + # Rename back to a simple non-NS node + attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e") + self.confirm(attr.name == "e" + and attr.nodeName == "e" + and attr.localName is None + and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE + and attr.prefix is None + and attr.value == "v" + and elem.getAttributeNode("a") is None + and elem.getAttributeNode("b") is None + and elem.getAttributeNode("c") is None + and elem.getAttributeNode("p:d") is None + and elem.getAttributeNodeNS( + "http://xml.python.org/ns", "c") is None + and elem.getAttributeNode("e").isSameNode(attr) + and attrmap["e"].isSameNode(attr)) + + self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr, + "http://xml.python.org/ns", "xmlns") + self.checkRenameNodeSharedConstraints(doc, attr) + doc.unlink() + + def testRenameElement(self): + doc = parseString("") + elem = doc.documentElement + + # Simple renaming + elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a") + self.confirm(elem.tagName == "a" + and elem.nodeName == "a" + and elem.localName is None + and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE + and elem.prefix is None + and elem.ownerDocument.isSameNode(doc)) + + # Rename to have a namespace, no prefix + elem = doc.renameNode(elem, "http://xml.python.org/ns", "b") + self.confirm(elem.tagName == "b" + and elem.nodeName == "b" + and elem.localName == "b" + and elem.namespaceURI == "http://xml.python.org/ns" + and elem.prefix is None + and elem.ownerDocument.isSameNode(doc)) + + # Rename to have a namespace, with prefix + elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c") + self.confirm(elem.tagName == "p:c" + and elem.nodeName == "p:c" + and elem.localName == "c" + and elem.namespaceURI == "http://xml.python.org/ns2" + and elem.prefix == "p" + and elem.ownerDocument.isSameNode(doc)) + + # Rename back to a simple non-NS node + elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d") + self.confirm(elem.tagName == "d" + and elem.nodeName == "d" + and elem.localName is None + and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE + and elem.prefix is None + and elem.ownerDocument.isSameNode(doc)) + + self.checkRenameNodeSharedConstraints(doc, elem) + doc.unlink() + + def testRenameOther(self): + # We have to create a comment node explicitly since not all DOM + # builders used with minidom add comments to the DOM. + doc = xml.dom.minidom.getDOMImplementation().createDocument( + xml.dom.EMPTY_NAMESPACE, "e", None) + node = doc.createComment("comment") + self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node, + xml.dom.EMPTY_NAMESPACE, "foo") + doc.unlink() + + def testWholeText(self): + doc = parseString("a") + elem = doc.documentElement + text = elem.childNodes[0] + self.assertEquals(text.nodeType, Node.TEXT_NODE) + + self.checkWholeText(text, "a") + elem.appendChild(doc.createTextNode("b")) + self.checkWholeText(text, "ab") + elem.insertBefore(doc.createCDATASection("c"), text) + self.checkWholeText(text, "cab") + + # make sure we don't cross other nodes + splitter = doc.createComment("comment") + elem.appendChild(splitter) + text2 = doc.createTextNode("d") + elem.appendChild(text2) + self.checkWholeText(text, "cab") + self.checkWholeText(text2, "d") + + x = doc.createElement("x") + elem.replaceChild(x, splitter) + splitter = x + self.checkWholeText(text, "cab") + self.checkWholeText(text2, "d") + + x = doc.createProcessingInstruction("y", "z") + elem.replaceChild(x, splitter) + splitter = x + self.checkWholeText(text, "cab") + self.checkWholeText(text2, "d") + + elem.removeChild(splitter) + self.checkWholeText(text, "cabd") + self.checkWholeText(text2, "cabd") + + def testPatch1094164(self): + doc = parseString("") elem = doc.documentElement - text1 = elem.firstChild - text2 = elem.lastChild - splitter = text1.nextSibling - elem.insertBefore(doc.createTextNode("b"), splitter) - elem.insertBefore(doc.createCDATASection("c"), text1) - return doc, elem, text1, splitter, text2 - - doc, elem, text1, splitter, text2 = setup() - text = text1.replaceWholeText("new content") - checkWholeText(text, "new content") - checkWholeText(text2, "d") - confirm(len(elem.childNodes) == 3) - - doc, elem, text1, splitter, text2 = setup() - text = text2.replaceWholeText("new content") - checkWholeText(text, "new content") - checkWholeText(text1, "cab") - confirm(len(elem.childNodes) == 5) - - doc, elem, text1, splitter, text2 = setup() - text = text1.replaceWholeText("") - checkWholeText(text2, "d") - confirm(text is None - and len(elem.childNodes) == 2) - -def testSchemaType(): - doc = parseString( - "\n" - " \n" - " \n" - "]>") - elem = doc.documentElement - # We don't want to rely on any specific loader at this point, so - # just make sure we can get to all the names, and that the - # DTD-based namespace is right. The names can vary by loader - # since each supports a different level of DTD information. - t = elem.schemaType - confirm(t.name is None - and t.namespace == xml.dom.EMPTY_NAMESPACE) - names = "id notid text enum ref refs ent ents nm nms".split() - for name in names: - a = elem.getAttributeNode(name) - t = a.schemaType - confirm(hasattr(t, "name") + e = elem.firstChild + self.confirm(e.parentNode is elem, "Before replaceChild()") + # Check that replacing a child with itself leaves the tree unchanged + elem.replaceChild(e, e) + self.confirm(e.parentNode is elem, "After replaceChild()") + + def testReplaceWholeText(self): + def setup(): + doc = parseString("ad") + elem = doc.documentElement + text1 = elem.firstChild + text2 = elem.lastChild + splitter = text1.nextSibling + elem.insertBefore(doc.createTextNode("b"), splitter) + elem.insertBefore(doc.createCDATASection("c"), text1) + return doc, elem, text1, splitter, text2 + + doc, elem, text1, splitter, text2 = setup() + text = text1.replaceWholeText("new content") + self.checkWholeText(text, "new content") + self.checkWholeText(text2, "d") + self.confirm(len(elem.childNodes) == 3) + + doc, elem, text1, splitter, text2 = setup() + text = text2.replaceWholeText("new content") + self.checkWholeText(text, "new content") + self.checkWholeText(text1, "cab") + self.confirm(len(elem.childNodes) == 5) + + doc, elem, text1, splitter, text2 = setup() + text = text1.replaceWholeText("") + self.checkWholeText(text2, "d") + self.confirm(text is None + and len(elem.childNodes) == 2) + + def testSchemaType(self): + doc = parseString( + "\n" + " \n" + " \n" + "]>") + elem = doc.documentElement + # We don't want to rely on any specific loader at this point, so + # just make sure we can get to all the names, and that the + # DTD-based namespace is right. The names can vary by loader + # since each supports a different level of DTD information. + t = elem.schemaType + self.confirm(t.name is None and t.namespace == xml.dom.EMPTY_NAMESPACE) + names = "id notid text enum ref refs ent ents nm nms".split() + for name in names: + a = elem.getAttributeNode(name) + t = a.schemaType + self.confirm(hasattr(t, "name") + and t.namespace == xml.dom.EMPTY_NAMESPACE) + + def testSetIdAttribute(self): + doc = parseString("") + e = doc.documentElement + a1 = e.getAttributeNode("a1") + a2 = e.getAttributeNode("a2") + self.confirm(doc.getElementById("v") is None + and not a1.isId + and not a2.isId) + e.setIdAttribute("a1") + self.confirm(e.isSameNode(doc.getElementById("v")) + and a1.isId + and not a2.isId) + e.setIdAttribute("a2") + self.confirm(e.isSameNode(doc.getElementById("v")) + and e.isSameNode(doc.getElementById("w")) + and a1.isId + and a2.isId) + # replace the a1 node; the new node should *not* be an ID + a3 = doc.createAttribute("a1") + a3.value = "v" + e.setAttributeNode(a3) + self.confirm(doc.getElementById("v") is None + and e.isSameNode(doc.getElementById("w")) + and not a1.isId + and a2.isId + and not a3.isId) + # renaming an attribute should not affect its ID-ness: + doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") + self.confirm(e.isSameNode(doc.getElementById("w")) + and a2.isId) + + def testSetIdAttributeNS(self): + NS1 = "http://xml.python.org/ns1" + NS2 = "http://xml.python.org/ns2" + doc = parseString("") + e = doc.documentElement + a1 = e.getAttributeNodeNS(NS1, "a1") + a2 = e.getAttributeNodeNS(NS2, "a2") + self.confirm(doc.getElementById("v") is None + and not a1.isId + and not a2.isId) + e.setIdAttributeNS(NS1, "a1") + self.confirm(e.isSameNode(doc.getElementById("v")) + and a1.isId + and not a2.isId) + e.setIdAttributeNS(NS2, "a2") + self.confirm(e.isSameNode(doc.getElementById("v")) + and e.isSameNode(doc.getElementById("w")) + and a1.isId + and a2.isId) + # replace the a1 node; the new node should *not* be an ID + a3 = doc.createAttributeNS(NS1, "a1") + a3.value = "v" + e.setAttributeNode(a3) + self.confirm(e.isSameNode(doc.getElementById("w"))) + self.confirm(not a1.isId) + self.confirm(a2.isId) + self.confirm(not a3.isId) + self.confirm(doc.getElementById("v") is None) + # renaming an attribute should not affect its ID-ness: + doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") + self.confirm(e.isSameNode(doc.getElementById("w")) + and a2.isId) + + def testSetIdAttributeNode(self): + NS1 = "http://xml.python.org/ns1" + NS2 = "http://xml.python.org/ns2" + doc = parseString("") + e = doc.documentElement + a1 = e.getAttributeNodeNS(NS1, "a1") + a2 = e.getAttributeNodeNS(NS2, "a2") + self.confirm(doc.getElementById("v") is None + and not a1.isId + and not a2.isId) + e.setIdAttributeNode(a1) + self.confirm(e.isSameNode(doc.getElementById("v")) + and a1.isId + and not a2.isId) + e.setIdAttributeNode(a2) + self.confirm(e.isSameNode(doc.getElementById("v")) + and e.isSameNode(doc.getElementById("w")) + and a1.isId + and a2.isId) + # replace the a1 node; the new node should *not* be an ID + a3 = doc.createAttributeNS(NS1, "a1") + a3.value = "v" + e.setAttributeNode(a3) + self.confirm(e.isSameNode(doc.getElementById("w"))) + self.confirm(not a1.isId) + self.confirm(a2.isId) + self.confirm(not a3.isId) + self.confirm(doc.getElementById("v") is None) + # renaming an attribute should not affect its ID-ness: + doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") + self.confirm(e.isSameNode(doc.getElementById("w")) + and a2.isId) + + def testPickledDocument(self): + doc = parseString("\n" + "\n" + " \n" + "]> text\n" + " ") + s = pickle.dumps(doc) + doc2 = pickle.loads(s) + stack = [(doc, doc2)] + while stack: + n1, n2 = stack.pop() + self.confirm(n1.nodeType == n2.nodeType + and len(n1.childNodes) == len(n2.childNodes) + and n1.nodeName == n2.nodeName + and not n1.isSameNode(n2) + and not n2.isSameNode(n1)) + if n1.nodeType == Node.DOCUMENT_TYPE_NODE: + len(n1.entities) + len(n2.entities) + len(n1.notations) + len(n2.notations) + self.confirm(len(n1.entities) == len(n2.entities) + and len(n1.notations) == len(n2.notations)) + for i in range(len(n1.notations)): + no1 = n1.notations.item(i) + no2 = n1.notations.item(i) + self.confirm(no1.name == no2.name + and no1.publicId == no2.publicId + and no1.systemId == no2.systemId) + statck.append((no1, no2)) + for i in range(len(n1.entities)): + e1 = n1.entities.item(i) + e2 = n2.entities.item(i) + self.confirm(e1.notationName == e2.notationName + and e1.publicId == e2.publicId + and e1.systemId == e2.systemId) + stack.append((e1, e2)) + if n1.nodeType != Node.DOCUMENT_NODE: + self.confirm(n1.ownerDocument.isSameNode(doc) + and n2.ownerDocument.isSameNode(doc2)) + for i in range(len(n1.childNodes)): + stack.append((n1.childNodes[i], n2.childNodes[i])) -def testSetIdAttribute(): - doc = parseString("") - e = doc.documentElement - a1 = e.getAttributeNode("a1") - a2 = e.getAttributeNode("a2") - confirm(doc.getElementById("v") is None - and not a1.isId - and not a2.isId) - e.setIdAttribute("a1") - confirm(e.isSameNode(doc.getElementById("v")) - and a1.isId - and not a2.isId) - e.setIdAttribute("a2") - confirm(e.isSameNode(doc.getElementById("v")) - and e.isSameNode(doc.getElementById("w")) - and a1.isId - and a2.isId) - # replace the a1 node; the new node should *not* be an ID - a3 = doc.createAttribute("a1") - a3.value = "v" - e.setAttributeNode(a3) - confirm(doc.getElementById("v") is None - and e.isSameNode(doc.getElementById("w")) - and not a1.isId - and a2.isId - and not a3.isId) - # renaming an attribute should not affect its ID-ness: - doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") - confirm(e.isSameNode(doc.getElementById("w")) - and a2.isId) - -def testSetIdAttributeNS(): - NS1 = "http://xml.python.org/ns1" - NS2 = "http://xml.python.org/ns2" - doc = parseString("") - e = doc.documentElement - a1 = e.getAttributeNodeNS(NS1, "a1") - a2 = e.getAttributeNodeNS(NS2, "a2") - confirm(doc.getElementById("v") is None - and not a1.isId - and not a2.isId) - e.setIdAttributeNS(NS1, "a1") - confirm(e.isSameNode(doc.getElementById("v")) - and a1.isId - and not a2.isId) - e.setIdAttributeNS(NS2, "a2") - confirm(e.isSameNode(doc.getElementById("v")) - and e.isSameNode(doc.getElementById("w")) - and a1.isId - and a2.isId) - # replace the a1 node; the new node should *not* be an ID - a3 = doc.createAttributeNS(NS1, "a1") - a3.value = "v" - e.setAttributeNode(a3) - confirm(e.isSameNode(doc.getElementById("w"))) - confirm(not a1.isId) - confirm(a2.isId) - confirm(not a3.isId) - confirm(doc.getElementById("v") is None) - # renaming an attribute should not affect its ID-ness: - doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") - confirm(e.isSameNode(doc.getElementById("w")) - and a2.isId) - -def testSetIdAttributeNode(): - NS1 = "http://xml.python.org/ns1" - NS2 = "http://xml.python.org/ns2" - doc = parseString("") - e = doc.documentElement - a1 = e.getAttributeNodeNS(NS1, "a1") - a2 = e.getAttributeNodeNS(NS2, "a2") - confirm(doc.getElementById("v") is None - and not a1.isId - and not a2.isId) - e.setIdAttributeNode(a1) - confirm(e.isSameNode(doc.getElementById("v")) - and a1.isId - and not a2.isId) - e.setIdAttributeNode(a2) - confirm(e.isSameNode(doc.getElementById("v")) - and e.isSameNode(doc.getElementById("w")) - and a1.isId - and a2.isId) - # replace the a1 node; the new node should *not* be an ID - a3 = doc.createAttributeNS(NS1, "a1") - a3.value = "v" - e.setAttributeNode(a3) - confirm(e.isSameNode(doc.getElementById("w"))) - confirm(not a1.isId) - confirm(a2.isId) - confirm(not a3.isId) - confirm(doc.getElementById("v") is None) - # renaming an attribute should not affect its ID-ness: - doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") - confirm(e.isSameNode(doc.getElementById("w")) - and a2.isId) - -def testPickledDocument(): - doc = parseString("\n" - "\n" - " \n" - "]> text\n" - " ") - s = pickle.dumps(doc) - doc2 = pickle.loads(s) - stack = [(doc, doc2)] - while stack: - n1, n2 = stack.pop() - confirm(n1.nodeType == n2.nodeType - and len(n1.childNodes) == len(n2.childNodes) - and n1.nodeName == n2.nodeName - and not n1.isSameNode(n2) - and not n2.isSameNode(n1)) - if n1.nodeType == Node.DOCUMENT_TYPE_NODE: - len(n1.entities) - len(n2.entities) - len(n1.notations) - len(n2.notations) - confirm(len(n1.entities) == len(n2.entities) - and len(n1.notations) == len(n2.notations)) - for i in range(len(n1.notations)): - no1 = n1.notations.item(i) - no2 = n1.notations.item(i) - confirm(no1.name == no2.name - and no1.publicId == no2.publicId - and no1.systemId == no2.systemId) - statck.append((no1, no2)) - for i in range(len(n1.entities)): - e1 = n1.entities.item(i) - e2 = n2.entities.item(i) - confirm(e1.notationName == e2.notationName - and e1.publicId == e2.publicId - and e1.systemId == e2.systemId) - stack.append((e1, e2)) - if n1.nodeType != Node.DOCUMENT_NODE: - confirm(n1.ownerDocument.isSameNode(doc) - and n2.ownerDocument.isSameNode(doc2)) - for i in range(len(n1.childNodes)): - stack.append((n1.childNodes[i], n2.childNodes[i])) - - -# --- MAIN PROGRAM - -names = sorted(globals().keys()) - -failed = [] - -try: - Node.allnodes -except AttributeError: - # We don't actually have the minidom from the standard library, - # but are picking up the PyXML version from site-packages. - def check_allnodes(): - pass -else: - def check_allnodes(): - confirm(len(Node.allnodes) == 0, - "assertion: len(Node.allnodes) == 0") - if len(Node.allnodes): - print("Garbage left over:") - if verbose: - print(Node.allnodes.items()[0:10]) - else: - # Don't print specific nodes if repeatable results - # are needed - print(len(Node.allnodes)) - Node.allnodes = {} - -for name in names: - if name.startswith("test"): - func = globals()[name] - try: - func() - check_allnodes() - except: - failed.append(name) - print("Test Failed: ", name) - sys.stdout.flush() - traceback.print_exception(*sys.exc_info()) - print(repr(sys.exc_info()[1])) - Node.allnodes = {} +def test_main(): + run_unittest(MinidomTest) -if failed: - print("\n\n\n**** Check for failures in these tests:") - for name in failed: - print(" " + name) +if __name__ == "__main__": + test_main() Modified: python/branches/p3yk/Lib/test/test_module.py ============================================================================== --- python/branches/p3yk/Lib/test/test_module.py (original) +++ python/branches/p3yk/Lib/test/test_module.py Fri Apr 27 21:54:29 2007 @@ -1,48 +1,61 @@ # Test the module type - -from test.test_support import verify, vereq, verbose, TestFailed +import unittest +from test.test_support import verbose, run_unittest import sys -module = type(sys) +ModuleType = type(sys) + +class ModuleTests(unittest.TestCase): + def test_uninitialized(self): + # An uninitialized module has no __dict__ or __name__, + # and __doc__ is None + foo = ModuleType.__new__(ModuleType) + self.failUnless(foo.__dict__ is None) + try: + s = foo.__name__ + self.fail("__name__ = %s" % repr(s)) + except AttributeError: + pass + self.assertEqual(foo.__doc__, ModuleType.__doc__) + + def test_no_docstring(self): + # Regularly initialized module, no docstring + foo = ModuleType("foo") + self.assertEqual(foo.__name__, "foo") + self.assertEqual(foo.__doc__, None) + self.assertEqual(foo.__dict__, {"__name__": "foo", "__doc__": None}) + + def test_ascii_docstring(self): + # ASCII docstring + foo = ModuleType("foo", "foodoc") + self.assertEqual(foo.__name__, "foo") + self.assertEqual(foo.__doc__, "foodoc") + self.assertEqual(foo.__dict__, + {"__name__": "foo", "__doc__": "foodoc"}) + + def test_unicode_docstring(self): + # Unicode docstring + foo = ModuleType("foo", u"foodoc\u1234") + self.assertEqual(foo.__name__, "foo") + self.assertEqual(foo.__doc__, u"foodoc\u1234") + self.assertEqual(foo.__dict__, + {"__name__": "foo", "__doc__": u"foodoc\u1234"}) + + def test_reinit(self): + # Reinitialization should not replace the __dict__ + foo = ModuleType("foo", u"foodoc\u1234") + foo.bar = 42 + d = foo.__dict__ + foo.__init__("foo", "foodoc") + self.assertEqual(foo.__name__, "foo") + self.assertEqual(foo.__doc__, "foodoc") + self.assertEqual(foo.bar, 42) + self.assertEqual(foo.__dict__, + {"__name__": "foo", "__doc__": "foodoc", "bar": 42}) + self.failUnless(foo.__dict__ is d) -# An uninitialized module has no __dict__ or __name__, and __doc__ is None -foo = module.__new__(module) -verify(foo.__dict__ is None) -try: - s = foo.__name__ -except AttributeError: - pass -else: - raise TestFailed, "__name__ = %s" % repr(s) -vereq(foo.__doc__, module.__doc__) - -# Regularly initialized module, no docstring -foo = module("foo") -vereq(foo.__name__, "foo") -vereq(foo.__doc__, None) -vereq(foo.__dict__, {"__name__": "foo", "__doc__": None}) - -# ASCII docstring -foo = module("foo", "foodoc") -vereq(foo.__name__, "foo") -vereq(foo.__doc__, "foodoc") -vereq(foo.__dict__, {"__name__": "foo", "__doc__": "foodoc"}) - -# Unicode docstring -foo = module("foo", u"foodoc\u1234") -vereq(foo.__name__, "foo") -vereq(foo.__doc__, u"foodoc\u1234") -vereq(foo.__dict__, {"__name__": "foo", "__doc__": u"foodoc\u1234"}) - -# Reinitialization should not replace the __dict__ -foo.bar = 42 -d = foo.__dict__ -foo.__init__("foo", "foodoc") -vereq(foo.__name__, "foo") -vereq(foo.__doc__, "foodoc") -vereq(foo.bar, 42) -vereq(foo.__dict__, {"__name__": "foo", "__doc__": "foodoc", "bar": 42}) -verify(foo.__dict__ is d) +def test_main(): + run_unittest(ModuleTests) -if verbose: - print("All OK") +if __name__ == '__main__': + test_main() Modified: python/branches/p3yk/Lib/test/test_multibytecodec.py ============================================================================== --- python/branches/p3yk/Lib/test/test_multibytecodec.py (original) +++ python/branches/p3yk/Lib/test/test_multibytecodec.py Fri Apr 27 21:54:29 2007 @@ -219,13 +219,7 @@ myunichr(x).encode('iso_2022_jp', 'ignore') def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test_MultibyteCodec)) - suite.addTest(unittest.makeSuite(Test_IncrementalEncoder)) - suite.addTest(unittest.makeSuite(Test_IncrementalDecoder)) - suite.addTest(unittest.makeSuite(Test_StreamWriter)) - suite.addTest(unittest.makeSuite(Test_ISO2022)) - test_support.run_suite(suite) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_normalization.py ============================================================================== --- python/branches/p3yk/Lib/test/test_normalization.py (original) +++ python/branches/p3yk/Lib/test/test_normalization.py Fri Apr 27 21:54:29 2007 @@ -1,5 +1,6 @@ -from test.test_support import (verbose, TestFailed, TestSkipped, verify, - open_urlresource) +from test.test_support import run_unittest, open_urlresource +import unittest + import sys import os from unicodedata import normalize @@ -29,60 +30,67 @@ raise RangeError return u"".join([unichr(x) for x in data]) -def test_main(): - part1_data = {} - for line in open_urlresource(TESTDATAURL): - if '#' in line: - line = line.split('#')[0] - line = line.strip() - if not line: - continue - if line.startswith("@Part"): - part = line.split()[0] - continue - if part == "@Part3": - # XXX we don't support PRI #29 yet, so skip these tests for now - continue - try: - c1,c2,c3,c4,c5 = [unistr(x) for x in line.split(';')[:-1]] - except RangeError: - # Skip unsupported characters; - # try atleast adding c1 if we are in part1 +class NormalizationTest(unittest.TestCase): + def test_main(self): + part1_data = {} + for line in open_urlresource(TESTDATAURL): + if '#' in line: + line = line.split('#')[0] + line = line.strip() + if not line: + continue + if line.startswith("@Part"): + part = line.split()[0] + continue + if part == "@Part3": + # XXX we don't support PRI #29 yet, so skip these tests for now + continue + try: + c1,c2,c3,c4,c5 = [unistr(x) for x in line.split(';')[:-1]] + except RangeError: + # Skip unsupported characters; + # try atleast adding c1 if we are in part1 + if part == "@Part1": + try: + c1 = unistr(line.split(';')[0]) + except RangeError: + pass + else: + part1_data[c1] = 1 + continue + + # Perform tests + self.failUnless(c2 == NFC(c1) == NFC(c2) == NFC(c3), line) + self.failUnless(c4 == NFC(c4) == NFC(c5), line) + self.failUnless(c3 == NFD(c1) == NFD(c2) == NFD(c3), line) + self.failUnless(c5 == NFD(c4) == NFD(c5), line) + self.failUnless(c4 == NFKC(c1) == NFKC(c2) == \ + NFKC(c3) == NFKC(c4) == NFKC(c5), + line) + self.failUnless(c5 == NFKD(c1) == NFKD(c2) == \ + NFKD(c3) == NFKD(c4) == NFKD(c5), + line) + + # Record part 1 data if part == "@Part1": - try: - c1=unistr(line.split(';')[0]) - except RangeError: - pass - else: - part1_data[c1] = 1 - continue - - if verbose: - print(line) - - # Perform tests - verify(c2 == NFC(c1) == NFC(c2) == NFC(c3), line) - verify(c4 == NFC(c4) == NFC(c5), line) - verify(c3 == NFD(c1) == NFD(c2) == NFD(c3), line) - verify(c5 == NFD(c4) == NFD(c5), line) - verify(c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5), - line) - verify(c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5), - line) - - # Record part 1 data - if part == "@Part1": - part1_data[c1] = 1 - - # Perform tests for all other data - for c in range(sys.maxunicode+1): - X = unichr(c) - if X in part1_data: - continue - assert X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X), c + part1_data[c1] = 1 - # Check for bug 834676 - normalize('NFC',u'\ud55c\uae00') + # Perform tests for all other data + for c in range(sys.maxunicode+1): + X = unichr(c) + if X in part1_data: + continue + self.failUnless(X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X), c) + + def test_bug_834676(self): + # Check for bug 834676 + normalize('NFC', u'\ud55c\uae00') + + +def test_main(): + # Hit the exception early + open_urlresource(TESTDATAURL) + run_unittest(NormalizationTest) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_ntpath.py ============================================================================== --- python/branches/p3yk/Lib/test/test_ntpath.py (original) +++ python/branches/p3yk/Lib/test/test_ntpath.py Fri Apr 27 21:54:29 2007 @@ -18,13 +18,14 @@ tester('ntpath.splitext("foo.ext")', ('foo', '.ext')) tester('ntpath.splitext("/foo/foo.ext")', ('/foo/foo', '.ext')) -tester('ntpath.splitext(".ext")', ('', '.ext')) +tester('ntpath.splitext(".ext")', ('.ext', '')) tester('ntpath.splitext("\\foo.ext\\foo")', ('\\foo.ext\\foo', '')) tester('ntpath.splitext("foo.ext\\")', ('foo.ext\\', '')) tester('ntpath.splitext("")', ('', '')) tester('ntpath.splitext("foo.bar.ext")', ('foo.bar', '.ext')) tester('ntpath.splitext("xx/foo.bar.ext")', ('xx/foo.bar', '.ext')) tester('ntpath.splitext("xx\\foo.bar.ext")', ('xx\\foo.bar', '.ext')) +tester('ntpath.splitext("c:a/b\\c.d")', ('c:a/b\\c', '.d')) tester('ntpath.splitdrive("c:\\foo\\bar")', ('c:', '\\foo\\bar')) @@ -133,6 +134,13 @@ tester('ntpath.expandvars("${{foo}}")', "baz1}") tester('ntpath.expandvars("$foo$foo")', "barbar") tester('ntpath.expandvars("$bar$bar")', "$bar$bar") + tester('ntpath.expandvars("%foo% bar")', "bar bar") + tester('ntpath.expandvars("%foo%bar")', "barbar") + tester('ntpath.expandvars("%foo%%foo%")', "barbar") + tester('ntpath.expandvars("%%foo%%foo%foo%")', "%foo%foobar") + tester('ntpath.expandvars("%?bar%")', "%?bar%") + tester('ntpath.expandvars("%foo%%bar")', "bar%bar") + tester('ntpath.expandvars("\'%foo%\'%bar")', "\'%foo%\'%bar") finally: os.environ.clear() os.environ.update(oldenv) @@ -149,6 +157,16 @@ else: tester('ntpath.abspath("C:\\")', "C:\\") +currentdir = os.path.split(os.getcwd())[-1] +tester('ntpath.relpath("a")', 'a') +tester('ntpath.relpath(os.path.abspath("a"))', 'a') +tester('ntpath.relpath("a/b")', 'a\\b') +tester('ntpath.relpath("../a/b")', '..\\a\\b') +tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a') +tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b') +tester('ntpath.relpath("a", "b/c")', '..\\..\\a') +tester('ntpath.relpath("//conky/mountpoint/a", "//conky/mountpoint/b/c")', '..\\..\\a') + if errors: raise TestFailed(str(errors) + " errors.") elif verbose: Deleted: /python/branches/p3yk/Lib/test/test_operations.py ============================================================================== --- /python/branches/p3yk/Lib/test/test_operations.py Fri Apr 27 21:54:29 2007 +++ (empty file) @@ -1,77 +0,0 @@ -# Python test set -- part 3, built-in operations. - - -print('3. Operations') -print('XXX Mostly not yet implemented') - - -print('3.1 Dictionary lookups fail if __cmp__() raises an exception') - -class BadDictKey: - - def __hash__(self): - return hash(self.__class__) - - def __eq__(self, other): - if isinstance(other, self.__class__): - print("raising error") - raise RuntimeError, "gotcha" - return other - -d = {} -x1 = BadDictKey() -x2 = BadDictKey() -d[x1] = 1 -for stmt in ['d[x2] = 2', - 'z = d[x2]', - 'x2 in d', - 'd.get(x2)', - 'd.setdefault(x2, 42)', - 'd.pop(x2)', - 'd.update({x2: 2})']: - try: - exec(stmt) - except RuntimeError: - print("%s: caught the RuntimeError outside" % (stmt,)) - else: - print("%s: No exception passed through!" % (stmt,)) # old CPython behavior - - -# Dict resizing bug, found by Jack Jansen in 2.2 CVS development. -# This version got an assert failure in debug build, infinite loop in -# release build. Unfortunately, provoking this kind of stuff requires -# a mix of inserts and deletes hitting exactly the right hash codes in -# exactly the right order, and I can't think of a randomized approach -# that would be *likely* to hit a failing case in reasonable time. - -d = {} -for i in range(5): - d[i] = i -for i in range(5): - del d[i] -for i in range(5, 9): # i==8 was the problem - d[i] = i - - -# Another dict resizing bug (SF bug #1456209). -# This caused Segmentation faults or Illegal instructions. - -class X(object): - def __hash__(self): - return 5 - def __eq__(self, other): - if resizing: - d.clear() - return False -d = {} -resizing = False -d[X()] = 1 -d[X()] = 2 -d[X()] = 3 -d[X()] = 4 -d[X()] = 5 -# now trigger a resize -resizing = True -d[9] = 6 - -print('resize bugs not triggered.') 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 Fri Apr 27 21:54:29 2007 @@ -143,6 +143,8 @@ self.failUnlessRaises(TypeError, operator.delslice, a, None, None) self.failUnless(operator.delslice(a, 2, 8) is None) self.assert_(a == [0, 1, 8, 9]) + operator.delslice(a, 0, test_support.MAX_Py_ssize_t) + self.assert_(a == []) def test_floordiv(self): self.failUnlessRaises(TypeError, operator.floordiv, 5) @@ -165,6 +167,8 @@ self.failUnlessRaises(TypeError, operator.getslice) self.failUnlessRaises(TypeError, operator.getslice, a, None, None) self.failUnless(operator.getslice(a, 4, 6) == [4, 5]) + b = operator.getslice(a, 0, test_support.MAX_Py_ssize_t) + self.assert_(b == a) def test_indexOf(self): self.failUnlessRaises(TypeError, operator.indexOf) @@ -300,6 +304,8 @@ self.failUnlessRaises(TypeError, operator.setslice, a, None, None, None) self.failUnless(operator.setslice(a, 1, 3, [2, 1]) is None) self.assert_(a == [0, 2, 1, 3]) + operator.setslice(a, 0, test_support.MAX_Py_ssize_t, []) + self.assert_(a == []) def test_sub(self): self.failUnlessRaises(TypeError, operator.sub) Modified: python/branches/p3yk/Lib/test/test_optparse.py ============================================================================== --- python/branches/p3yk/Lib/test/test_optparse.py (original) +++ python/branches/p3yk/Lib/test/test_optparse.py Fri Apr 27 21:54:29 2007 @@ -1631,18 +1631,8 @@ "option -l: invalid integer value: '0x12x'") -def _testclasses(): - mod = sys.modules[__name__] - return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] - -def suite(): - suite = unittest.TestSuite() - for testclass in _testclasses(): - suite.addTest(unittest.makeSuite(testclass)) - return suite - def test_main(): - test_support.run_suite(suite()) + test_support.run_unittest(__name__) if __name__ == '__main__': - unittest.main() + test_main() 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 Fri Apr 27 21:54:29 2007 @@ -240,6 +240,15 @@ os.utime(self.fname, (t1, t1)) self.assertEquals(os.stat(self.fname).st_mtime, t1) + def test_1686475(self): + # Verify that an open file can be stat'ed + try: + os.stat(r"c:\pagefile.sys") + except WindowsError as e: + if e == 2: # file does not exist; cannot run test + return + self.fail("Could not stat pagefile.sys") + from test import mapping_tests class EnvironTests(mapping_tests.BasicTestMappingProtocol): @@ -272,75 +281,104 @@ from os.path import join # Build: - # TESTFN/ a file kid and two directory kids + # TESTFN/ + # TEST1/ a file kid and two directory kids # tmp1 # SUB1/ a file kid and a directory kid - # tmp2 - # SUB11/ no kids - # SUB2/ just a file kid - # tmp3 - sub1_path = join(test_support.TESTFN, "SUB1") + # tmp2 + # SUB11/ no kids + # SUB2/ a file kid and a dirsymlink kid + # tmp3 + # link/ a symlink to TESTFN.2 + # TEST2/ + # tmp4 a lone file + walk_path = join(test_support.TESTFN, "TEST1") + sub1_path = join(walk_path, "SUB1") sub11_path = join(sub1_path, "SUB11") - sub2_path = join(test_support.TESTFN, "SUB2") - tmp1_path = join(test_support.TESTFN, "tmp1") + sub2_path = join(walk_path, "SUB2") + tmp1_path = join(walk_path, "tmp1") tmp2_path = join(sub1_path, "tmp2") tmp3_path = join(sub2_path, "tmp3") + link_path = join(sub2_path, "link") + t2_path = join(test_support.TESTFN, "TEST2") + tmp4_path = join(test_support.TESTFN, "TEST2", "tmp4") # Create stuff. os.makedirs(sub11_path) os.makedirs(sub2_path) - for path in tmp1_path, tmp2_path, tmp3_path: + os.makedirs(t2_path) + for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path: f = open(path, "w") f.write("I'm " + path + " and proud of it. Blame test_os.\n") f.close() + if hasattr(os, "symlink"): + os.symlink(os.path.abspath(t2_path), link_path) + sub2_tree = (sub2_path, ["link"], ["tmp3"]) + else: + sub2_tree = (sub2_path, [], ["tmp3"]) # Walk top-down. - all = list(os.walk(test_support.TESTFN)) + all = list(os.walk(walk_path)) self.assertEqual(len(all), 4) # We can't know which order SUB1 and SUB2 will appear in. # Not flipped: TESTFN, SUB1, SUB11, SUB2 # flipped: TESTFN, SUB2, SUB1, SUB11 flipped = all[0][1][0] != "SUB1" all[0][1].sort() - self.assertEqual(all[0], (test_support.TESTFN, ["SUB1", "SUB2"], ["tmp1"])) + self.assertEqual(all[0], (walk_path, ["SUB1", "SUB2"], ["tmp1"])) self.assertEqual(all[1 + flipped], (sub1_path, ["SUB11"], ["tmp2"])) self.assertEqual(all[2 + flipped], (sub11_path, [], [])) - self.assertEqual(all[3 - 2 * flipped], (sub2_path, [], ["tmp3"])) + self.assertEqual(all[3 - 2 * flipped], sub2_tree) # Prune the search. all = [] - for root, dirs, files in os.walk(test_support.TESTFN): + for root, dirs, files in os.walk(walk_path): all.append((root, dirs, files)) # Don't descend into SUB1. if 'SUB1' in dirs: # Note that this also mutates the dirs we appended to all! dirs.remove('SUB1') self.assertEqual(len(all), 2) - self.assertEqual(all[0], (test_support.TESTFN, ["SUB2"], ["tmp1"])) - self.assertEqual(all[1], (sub2_path, [], ["tmp3"])) + self.assertEqual(all[0], (walk_path, ["SUB2"], ["tmp1"])) + self.assertEqual(all[1], sub2_tree) # Walk bottom-up. - all = list(os.walk(test_support.TESTFN, topdown=False)) + all = list(os.walk(walk_path, topdown=False)) self.assertEqual(len(all), 4) # We can't know which order SUB1 and SUB2 will appear in. # Not flipped: SUB11, SUB1, SUB2, TESTFN # flipped: SUB2, SUB11, SUB1, TESTFN flipped = all[3][1][0] != "SUB1" all[3][1].sort() - self.assertEqual(all[3], (test_support.TESTFN, ["SUB1", "SUB2"], ["tmp1"])) + self.assertEqual(all[3], (walk_path, ["SUB1", "SUB2"], ["tmp1"])) self.assertEqual(all[flipped], (sub11_path, [], [])) self.assertEqual(all[flipped + 1], (sub1_path, ["SUB11"], ["tmp2"])) - self.assertEqual(all[2 - 2 * flipped], (sub2_path, [], ["tmp3"])) + self.assertEqual(all[2 - 2 * flipped], sub2_tree) + + if hasattr(os, "symlink"): + # Walk, following symlinks. + for root, dirs, files in os.walk(walk_path, followlinks=True): + if root == link_path: + self.assertEqual(dirs, []) + self.assertEqual(files, ["tmp4"]) + break + else: + self.fail("Didn't follow symlink with followlinks=True") + def tearDown(self): # Tear everything down. This is a decent use for bottom-up on # Windows, which doesn't have a recursive delete command. The # (not so) subtlety is that rmdir will fail unless the dir's # kids are removed first, so bottom up is essential. for root, dirs, files in os.walk(test_support.TESTFN, topdown=False): for name in files: - os.remove(join(root, name)) + os.remove(os.path.join(root, name)) for name in dirs: - os.rmdir(join(root, name)) + dirname = os.path.join(root, name) + if not os.path.islink(dirname): + os.rmdir(dirname) + else: + os.remove(dirname) os.rmdir(test_support.TESTFN) class MakedirTests (unittest.TestCase): 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 Fri Apr 27 21:54:29 2007 @@ -1,7 +1,7 @@ from test import test_support test_support.requires('audio') -from test.test_support import verbose, findfile, TestFailed, TestSkipped +from test.test_support import verbose, findfile, TestSkipped import errno import fcntl @@ -12,6 +12,7 @@ import sunaudio import time import audioop +import unittest # Arggh, AFMT_S16_NE not defined on all platforms -- seems to be a # fairly recent addition to OSS. @@ -33,131 +34,143 @@ fp.close() if enc != SND_FORMAT_MULAW_8: - print("Expect .au file with 8-bit mu-law samples") - return + raise RuntimeError("Expect .au file with 8-bit mu-law samples") # Convert the data to 16-bit signed. data = audioop.ulaw2lin(data, 2) return (data, rate, 16, nchannels) -# version of assert that still works with -O -def _assert(expr, message=None): - if not expr: - raise AssertionError(message or "assertion failed") +class OSSAudioDevTests(unittest.TestCase): -def play_sound_file(data, rate, ssize, nchannels): - try: - dsp = ossaudiodev.open('w') - except IOError as msg: - if msg.args[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise TestSkipped, msg - raise TestFailed, msg - - # at least check that these methods can be invoked - dsp.bufsize() - dsp.obufcount() - dsp.obuffree() - dsp.getptr() - dsp.fileno() - - # Make sure the read-only attributes work. - _assert(dsp.closed is False, "dsp.closed is not False") - _assert(dsp.name == "/dev/dsp") - _assert(dsp.mode == 'w', "bad dsp.mode: %r" % dsp.mode) - - # And make sure they're really read-only. - for attr in ('closed', 'name', 'mode'): + def play_sound_file(self, data, rate, ssize, nchannels): try: - setattr(dsp, attr, 42) - raise RuntimeError("dsp.%s not read-only" % attr) - except TypeError: - pass - - # Compute expected running time of sound sample (in seconds). - expected_time = float(len(data)) / (ssize/8) / nchannels / rate - - # set parameters based on .au file headers - dsp.setparameters(AFMT_S16_NE, nchannels, rate) - print(("playing test sound file (expected running time: %.2f sec)" - % expected_time)) - t1 = time.time() - dsp.write(data) - dsp.close() - t2 = time.time() - elapsed_time = t2 - t1 - - percent_diff = (abs(elapsed_time - expected_time) / expected_time) * 100 - _assert(percent_diff <= 10.0, \ - ("elapsed time (%.2f sec) > 10%% off of expected time (%.2f sec)" - % (elapsed_time, expected_time))) - -def test_setparameters(dsp): - # Two configurations for testing: - # config1 (8-bit, mono, 8 kHz) should work on even the most - # ancient and crufty sound card, but maybe not on special- - # purpose high-end hardware - # config2 (16-bit, stereo, 44.1kHz) should work on all but the - # most ancient and crufty hardware - config1 = (ossaudiodev.AFMT_U8, 1, 8000) - config2 = (AFMT_S16_NE, 2, 44100) - - for config in [config1, config2]: - (fmt, channels, rate) = config - if (dsp.setfmt(fmt) == fmt and - dsp.channels(channels) == channels and - dsp.speed(rate) == rate): - break - else: - raise RuntimeError("unable to set audio sampling parameters: " - "you must have really weird audio hardware") + dsp = ossaudiodev.open('w') + except IOError as msg: + if msg.args[0] in (errno.EACCES, errno.ENOENT, + errno.ENODEV, errno.EBUSY): + raise TestSkipped(msg) + raise + + # at least check that these methods can be invoked + dsp.bufsize() + dsp.obufcount() + dsp.obuffree() + dsp.getptr() + dsp.fileno() + + # Make sure the read-only attributes work. + self.failUnless(dsp.close) + self.assertEqual(dsp.name, "/dev/dsp") + self.assertEqual(dsp.mode, "w", "bad dsp.mode: %r" % dsp.mode) + + # And make sure they're really read-only. + for attr in ('closed', 'name', 'mode'): + try: + setattr(dsp, attr, 42) + except TypeError: + pass + else: + self.fail("dsp.%s not read-only" % attr) + + # Compute expected running time of sound sample (in seconds). + expected_time = float(len(data)) / (ssize/8) / nchannels / rate + + # set parameters based on .au file headers + dsp.setparameters(AFMT_S16_NE, nchannels, rate) + print ("playing test sound file (expected running time: %.2f sec)" + % expected_time) + t1 = time.time() + dsp.write(data) + dsp.close() + t2 = time.time() + elapsed_time = t2 - t1 + + percent_diff = (abs(elapsed_time - expected_time) / expected_time) * 100 + self.failUnless(percent_diff <= 10.0, + "elapsed time > 10% off of expected time") + + def set_parameters(self, dsp): + # Two configurations for testing: + # config1 (8-bit, mono, 8 kHz) should work on even the most + # ancient and crufty sound card, but maybe not on special- + # purpose high-end hardware + # config2 (16-bit, stereo, 44.1kHz) should work on all but the + # most ancient and crufty hardware + config1 = (ossaudiodev.AFMT_U8, 1, 8000) + config2 = (AFMT_S16_NE, 2, 44100) + + for config in [config1, config2]: + (fmt, channels, rate) = config + if (dsp.setfmt(fmt) == fmt and + dsp.channels(channels) == channels and + dsp.speed(rate) == rate): + break + else: + raise RuntimeError("unable to set audio sampling parameters: " + "you must have really weird audio hardware") - # setparameters() should be able to set this configuration in - # either strict or non-strict mode. - result = dsp.setparameters(fmt, channels, rate, False) - _assert(result == (fmt, channels, rate), - "setparameters%r: returned %r" % (config, result)) - result = dsp.setparameters(fmt, channels, rate, True) - _assert(result == (fmt, channels, rate), - "setparameters%r: returned %r" % (config, result)) - -def test_bad_setparameters(dsp): - - # Now try some configurations that are presumably bogus: eg. 300 - # channels currently exceeds even Hollywood's ambitions, and - # negative sampling rate is utter nonsense. setparameters() should - # accept these in non-strict mode, returning something other than - # was requested, but should barf in strict mode. - fmt = AFMT_S16_NE - rate = 44100 - channels = 2 - for config in [(fmt, 300, rate), # ridiculous nchannels - (fmt, -5, rate), # impossible nchannels - (fmt, channels, -50), # impossible rate - ]: - (fmt, channels, rate) = config + # setparameters() should be able to set this configuration in + # either strict or non-strict mode. result = dsp.setparameters(fmt, channels, rate, False) - _assert(result != config, - "setparameters: unexpectedly got requested configuration") + self.assertEqual(result, (fmt, channels, rate), + "setparameters%r: returned %r" % (config, result)) + result = dsp.setparameters(fmt, channels, rate, True) + self.assertEqual(result, (fmt, channels, rate), + "setparameters%r: returned %r" % (config, result)) + + def set_bad_parameters(self, dsp): + + # Now try some configurations that are presumably bogus: eg. 300 + # channels currently exceeds even Hollywood's ambitions, and + # negative sampling rate is utter nonsense. setparameters() should + # accept these in non-strict mode, returning something other than + # was requested, but should barf in strict mode. + fmt = AFMT_S16_NE + rate = 44100 + channels = 2 + for config in [(fmt, 300, rate), # ridiculous nchannels + (fmt, -5, rate), # impossible nchannels + (fmt, channels, -50), # impossible rate + ]: + (fmt, channels, rate) = config + result = dsp.setparameters(fmt, channels, rate, False) + self.failIfEqual(result, config, + "unexpectedly got requested configuration") + + try: + result = dsp.setparameters(fmt, channels, rate, True) + except ossaudiodev.OSSAudioError as err: + pass + else: + self.fail("expected OSSAudioError") + + def test_playback(self): + sound_info = read_sound_file(findfile('audiotest.au')) + self.play_sound_file(*sound_info) + + def test_set_parameters(self): + dsp = ossaudiodev.open("w") try: - result = dsp.setparameters(fmt, channels, rate, True) - raise AssertionError("setparameters: expected OSSAudioError") - except ossaudiodev.OSSAudioError as err: - print("setparameters: got OSSAudioError as expected") - -def test(): - (data, rate, ssize, nchannels) = read_sound_file(findfile('audiotest.au')) - play_sound_file(data, rate, ssize, nchannels) + self.set_parameters(dsp) - dsp = ossaudiodev.open("w") - try: - test_setparameters(dsp) + # Disabled because it fails under Linux 2.6 with ALSA's OSS + # emulation layer. + #self.set_bad_parameters(dsp) + finally: + dsp.close() + self.failUnless(dsp.closed) - # Disabled because it fails under Linux 2.6 with ALSA's OSS - # emulation layer. - #test_bad_setparameters(dsp) - finally: - dsp.close() - _assert(dsp.closed is True, "dsp.closed is not True") -test() +def test_main(): + try: + dsp = ossaudiodev.open('w') + except IOError as msg: + if msg.args[0] in (errno.EACCES, errno.ENOENT, + errno.ENODEV, errno.EBUSY): + raise TestSkipped(msg) + raise + test_support.run_unittest(__name__) + +if __name__ == "__main__": + test_main() Modified: python/branches/p3yk/Lib/test/test_peepholer.py ============================================================================== --- python/branches/p3yk/Lib/test/test_peepholer.py (original) +++ python/branches/p3yk/Lib/test/test_peepholer.py Fri Apr 27 21:54:29 2007 @@ -49,6 +49,11 @@ self.assert_(elem not in asm) for elem in ('LOAD_CONST', '(None)'): self.assert_(elem in asm) + def f(): + 'Adding a docstring made this test fail in Py2.5.0' + return None + self.assert_('LOAD_CONST' in disassemble(f)) + self.assert_('LOAD_GLOBAL' not in disassemble(f)) def test_while_one(self): # Skip over: LOAD_CONST trueconst JUMP_IF_FALSE xx POP_TOP @@ -195,14 +200,14 @@ # There should be one jump for the while loop. self.assertEqual(asm.split().count('JUMP_ABSOLUTE'), 1) self.assertEqual(asm.split().count('RETURN_VALUE'), 2) - + def test_make_function_doesnt_bail(self): def f(): - def g()->1+1: + def g()->1+1: pass return g asm = disassemble(f) - self.assert_('BINARY_ADD' not in asm) + self.assert_('BINARY_ADD' not in asm) def test_main(verbose=None): Modified: python/branches/p3yk/Lib/test/test_popen2.py ============================================================================== --- python/branches/p3yk/Lib/test/test_popen2.py (original) +++ python/branches/p3yk/Lib/test/test_popen2.py Fri Apr 27 21:54:29 2007 @@ -1,78 +1,92 @@ #! /usr/bin/env python -"""Test script for popen2.py - Christian Tismer -""" +"""Test script for popen2.py""" import os import sys -from test.test_support import TestSkipped, reap_children +import unittest +import popen2 -# popen2 contains its own testing routine -# which is especially useful to see if open files -# like stdin can be read successfully by a forked -# subprocess. - -def main(): - print("Test popen2 module:") - if (sys.platform[:4] == 'beos' or sys.platform[:6] == 'atheos') \ - and __name__ != '__main__': - # Locks get messed up or something. Generally we're supposed - # to avoid mixing "posix" fork & exec with native threads, and - # they may be right about that after all. - raise TestSkipped, "popen2() doesn't work during import on " + sys.platform - try: - from os import popen - except ImportError: - # if we don't have os.popen, check that - # we have os.fork. if not, skip the test - # (by raising an ImportError) - from os import fork - import popen2 - popen2._test() - - -def _test(): - # same test as popen2._test(), but using the os.popen*() API - print("Testing os module:") - import popen2 - # When the test runs, there shouldn't be any open pipes - popen2._cleanup() - assert not popen2._active, "Active pipes when test starts " + repr([c.cmd for c in popen2._active]) - cmd = "cat" - teststr = "ab cd\n" +from test.test_support import TestSkipped, run_unittest, reap_children + +if sys.platform[:4] == 'beos' or sys.platform[:6] == 'atheos': + # Locks get messed up or something. Generally we're supposed + # to avoid mixing "posix" fork & exec with native threads, and + # they may be right about that after all. + raise TestSkipped("popen2() doesn't work on " + sys.platform) + +# if we don't have os.popen, check that +# we have os.fork. if not, skip the test +# (by raising an ImportError) +try: + from os import popen + del popen +except ImportError: + from os import fork + del fork + +class Popen2Test(unittest.TestCase): + cmd = "cat" if os.name == "nt": cmd = "more" + teststr = "ab cd\n" # "more" doesn't act the same way across Windows flavors, # sometimes adding an extra newline at the start or the # end. So we strip whitespace off both ends for comparison. expected = teststr.strip() - print("testing popen2...") - w, r = os.popen2(cmd) - w.write(teststr) - w.close() - got = r.read() - if got.strip() != expected: - raise ValueError("wrote %r read %r" % (teststr, got)) - print("testing popen3...") - try: - w, r, e = os.popen3([cmd]) - except: - w, r, e = os.popen3(cmd) - w.write(teststr) - w.close() - got = r.read() - if got.strip() != expected: - raise ValueError("wrote %r read %r" % (teststr, got)) - got = e.read() - if got: - raise ValueError("unexpected %r on stderr" % (got,)) - for inst in popen2._active[:]: - inst.wait() - popen2._cleanup() - if popen2._active: - raise ValueError("_active not empty") - print("All OK") - -main() -_test() -reap_children() + + def setUp(self): + popen2._cleanup() + # When the test runs, there shouldn't be any open pipes + self.assertFalse(popen2._active, "Active pipes when test starts" + + repr([c.cmd for c in popen2._active])) + + def tearDown(self): + for inst in popen2._active: + inst.wait() + popen2._cleanup() + self.assertFalse(popen2._active, "_active not empty") + reap_children() + + def validate_output(self, teststr, expected_out, r, w, e=None): + w.write(teststr) + w.close() + got = r.read() + self.assertEquals(expected_out, got.strip(), "wrote %r read %r" % + (teststr, got)) + + if e is not None: + got = e.read() + self.assertFalse(got, "unexpected %r on stderr" % got) + + def test_popen2(self): + r, w = popen2.popen2(self.cmd) + self.validate_output(self.teststr, self.expected, r, w) + + def test_popen3(self): + if os.name == 'posix': + r, w, e = popen2.popen3([self.cmd]) + self.validate_output(self.teststr, self.expected, r, w, e) + + r, w, e = popen2.popen3(self.cmd) + self.validate_output(self.teststr, self.expected, r, w, e) + + def test_os_popen2(self): + # same test as test_popen2(), but using the os.popen*() API + w, r = os.popen2(self.cmd) + self.validate_output(self.teststr, self.expected, r, w) + + def test_os_popen3(self): + # same test as test_popen3(), but using the os.popen*() API + if os.name == 'posix': + w, r, e = os.popen3([self.cmd]) + self.validate_output(self.teststr, self.expected, r, w, e) + + w, r, e = os.popen3(self.cmd) + self.validate_output(self.teststr, self.expected, r, w, e) + + +def test_main(): + run_unittest(Popen2Test) + +if __name__ == "__main__": + test_main() Modified: python/branches/p3yk/Lib/test/test_posixpath.py ============================================================================== --- python/branches/p3yk/Lib/test/test_posixpath.py (original) +++ python/branches/p3yk/Lib/test/test_posixpath.py Fri Apr 27 21:54:29 2007 @@ -2,15 +2,29 @@ from test import test_support import posixpath, os -from posixpath import realpath, abspath, join, dirname, basename +from posixpath import realpath, abspath, join, dirname, basename, relpath # An absolute path to a temporary filename for testing. We can't rely on TESTFN # being an absolute path, so we need this. ABSTFN = abspath(test_support.TESTFN) +def safe_rmdir(dirname): + try: + os.rmdir(dirname) + except OSError: + pass + class PosixPathTest(unittest.TestCase): + def setUp(self): + self.tearDown() + + def tearDown(self): + for suffix in ["", "1", "2"]: + test_support.unlink(test_support.TESTFN + suffix) + safe_rmdir(test_support.TESTFN + suffix) + def assertIs(self, a, b): self.assert_(a is b) @@ -43,15 +57,27 @@ self.assertRaises(TypeError, posixpath.split) - def test_splitext(self): - self.assertEqual(posixpath.splitext("foo.ext"), ("foo", ".ext")) - self.assertEqual(posixpath.splitext("/foo/foo.ext"), ("/foo/foo", ".ext")) - self.assertEqual(posixpath.splitext(".ext"), ("", ".ext")) - self.assertEqual(posixpath.splitext("/foo.ext/foo"), ("/foo.ext/foo", "")) - self.assertEqual(posixpath.splitext("foo.ext/"), ("foo.ext/", "")) - self.assertEqual(posixpath.splitext(""), ("", "")) - self.assertEqual(posixpath.splitext("foo.bar.ext"), ("foo.bar", ".ext")) + def splitextTest(self, path, filename, ext): + self.assertEqual(posixpath.splitext(path), (filename, ext)) + self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext)) + self.assertEqual(posixpath.splitext("abc/" + path), ("abc/" + filename, ext)) + self.assertEqual(posixpath.splitext("abc.def/" + path), ("abc.def/" + filename, ext)) + self.assertEqual(posixpath.splitext("/abc.def/" + path), ("/abc.def/" + filename, ext)) + self.assertEqual(posixpath.splitext(path + "/"), (filename + ext + "/", "")) + def test_splitext(self): + self.splitextTest("foo.bar", "foo", ".bar") + self.splitextTest("foo.boo.bar", "foo.boo", ".bar") + self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar") + self.splitextTest(".csh.rc", ".csh", ".rc") + self.splitextTest("nodots", "nodots", "") + self.splitextTest(".cshrc", ".cshrc", "") + self.splitextTest("...manydots", "...manydots", "") + self.splitextTest("...manydots.ext", "...manydots", ".ext") + self.splitextTest(".", ".", "") + self.splitextTest("..", "..", "") + self.splitextTest("........", "........", "") + self.splitextTest("", "", "") self.assertRaises(TypeError, posixpath.splitext) def test_isabs(self): @@ -113,7 +139,6 @@ finally: if not f.closed: f.close() - os.remove(test_support.TESTFN) def test_time(self): f = open(test_support.TESTFN, "wb") @@ -135,7 +160,6 @@ finally: if not f.closed: f.close() - os.remove(test_support.TESTFN) def test_islink(self): self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False) @@ -154,14 +178,6 @@ finally: if not f.close(): f.close() - try: - os.remove(test_support.TESTFN + "1") - except os.error: - pass - try: - os.remove(test_support.TESTFN + "2") - except os.error: - pass self.assertRaises(TypeError, posixpath.islink) @@ -176,10 +192,6 @@ finally: if not f.close(): f.close() - try: - os.remove(test_support.TESTFN) - except os.error: - pass self.assertRaises(TypeError, posixpath.exists) @@ -197,14 +209,6 @@ finally: if not f.close(): f.close() - try: - os.remove(test_support.TESTFN) - except os.error: - pass - try: - os.rmdir(test_support.TESTFN) - except os.error: - pass self.assertRaises(TypeError, posixpath.isdir) @@ -222,67 +226,51 @@ finally: if not f.close(): f.close() - try: - os.remove(test_support.TESTFN) - except os.error: - pass - try: - os.rmdir(test_support.TESTFN) - except os.error: - pass self.assertRaises(TypeError, posixpath.isdir) - def test_samefile(self): - f = open(test_support.TESTFN + "1", "wb") - try: - f.write("foo") - f.close() + def test_samefile(self): + f = open(test_support.TESTFN + "1", "wb") + try: + f.write("foo") + f.close() + self.assertIs( + posixpath.samefile( + test_support.TESTFN + "1", + test_support.TESTFN + "1" + ), + True + ) + # If we don't have links, assume that os.stat doesn't return resonable + # inode information and thus, that samefile() doesn't work + if hasattr(os, "symlink"): + os.symlink( + test_support.TESTFN + "1", + test_support.TESTFN + "2" + ) self.assertIs( posixpath.samefile( test_support.TESTFN + "1", - test_support.TESTFN + "1" + test_support.TESTFN + "2" ), True ) - # If we don't have links, assume that os.stat doesn't return resonable - # inode information and thus, that samefile() doesn't work - if hasattr(os, "symlink"): - os.symlink( + os.remove(test_support.TESTFN + "2") + f = open(test_support.TESTFN + "2", "wb") + f.write("bar") + f.close() + self.assertIs( + posixpath.samefile( test_support.TESTFN + "1", test_support.TESTFN + "2" - ) - self.assertIs( - posixpath.samefile( - test_support.TESTFN + "1", - test_support.TESTFN + "2" - ), - True - ) - os.remove(test_support.TESTFN + "2") - f = open(test_support.TESTFN + "2", "wb") - f.write("bar") - f.close() - self.assertIs( - posixpath.samefile( - test_support.TESTFN + "1", - test_support.TESTFN + "2" - ), - False - ) - finally: - if not f.close(): - f.close() - try: - os.remove(test_support.TESTFN + "1") - except os.error: - pass - try: - os.remove(test_support.TESTFN + "2") - except os.error: - pass + ), + False + ) + finally: + if not f.close(): + f.close() - self.assertRaises(TypeError, posixpath.samefile) + self.assertRaises(TypeError, posixpath.samefile) def test_samestat(self): f = open(test_support.TESTFN + "1", "wb") @@ -322,14 +310,6 @@ finally: if not f.close(): f.close() - try: - os.remove(test_support.TESTFN + "1") - except os.error: - pass - try: - os.remove(test_support.TESTFN + "2") - except os.error: - pass self.assertRaises(TypeError, posixpath.samestat) @@ -409,7 +389,7 @@ os.symlink(ABSTFN+"1", ABSTFN) self.assertEqual(realpath(ABSTFN), ABSTFN+"1") finally: - self.safe_remove(ABSTFN) + test_support.unlink(ABSTFN) def test_realpath_symlink_loops(self): # Bug #930024, return the path unchanged if we get into an infinite @@ -429,9 +409,9 @@ self.assertEqual(realpath(basename(ABSTFN)), ABSTFN) finally: os.chdir(old_path) - self.safe_remove(ABSTFN) - self.safe_remove(ABSTFN+"1") - self.safe_remove(ABSTFN+"2") + test_support.unlink(ABSTFN) + test_support.unlink(ABSTFN+"1") + test_support.unlink(ABSTFN+"2") def test_realpath_resolve_parents(self): # We also need to resolve any symlinks in the parents of a relative @@ -448,9 +428,9 @@ self.assertEqual(realpath("a"), ABSTFN + "/y/a") finally: os.chdir(old_path) - self.safe_remove(ABSTFN + "/k") - self.safe_rmdir(ABSTFN + "/y") - self.safe_rmdir(ABSTFN) + test_support.unlink(ABSTFN + "/k") + safe_rmdir(ABSTFN + "/y") + safe_rmdir(ABSTFN) def test_realpath_resolve_before_normalizing(self): # Bug #990669: Symbolic links should be resolved before we @@ -474,10 +454,10 @@ self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."), ABSTFN + "/k") finally: os.chdir(old_path) - self.safe_remove(ABSTFN + "/link-y") - self.safe_rmdir(ABSTFN + "/k/y") - self.safe_rmdir(ABSTFN + "/k") - self.safe_rmdir(ABSTFN) + test_support.unlink(ABSTFN + "/link-y") + safe_rmdir(ABSTFN + "/k/y") + safe_rmdir(ABSTFN + "/k") + safe_rmdir(ABSTFN) def test_realpath_resolve_first(self): # Bug #1213894: The first component of the path, if not absolute, @@ -495,20 +475,24 @@ self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k") finally: os.chdir(old_path) - self.safe_remove(ABSTFN + "link") - self.safe_rmdir(ABSTFN + "/k") - self.safe_rmdir(ABSTFN) - - # Convenience functions for removing temporary files. - def pass_os_error(self, func, filename): - try: func(filename) - except OSError: pass + test_support.unlink(ABSTFN + "link") + safe_rmdir(ABSTFN + "/k") + safe_rmdir(ABSTFN) - def safe_remove(self, filename): - self.pass_os_error(os.remove, filename) - - def safe_rmdir(self, dirname): - self.pass_os_error(os.rmdir, dirname) + def test_relpath(self): + (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar") + try: + curdir = os.path.split(os.getcwd())[-1] + self.assertRaises(ValueError, posixpath.relpath, "") + self.assertEqual(posixpath.relpath("a"), "a") + self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a") + self.assertEqual(posixpath.relpath("a/b"), "a/b") + self.assertEqual(posixpath.relpath("../a/b"), "../a/b") + self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a") + self.assertEqual(posixpath.relpath("a/b", "../c"), "../"+curdir+"/a/b") + self.assertEqual(posixpath.relpath("a", "b/c"), "../../a") + finally: + os.getcwd = real_getcwd def test_main(): test_support.run_unittest(PosixPathTest) Modified: python/branches/p3yk/Lib/test/test_pty.py ============================================================================== --- python/branches/p3yk/Lib/test/test_pty.py (original) +++ python/branches/p3yk/Lib/test/test_pty.py Fri Apr 27 21:54:29 2007 @@ -1,5 +1,9 @@ -import pty, os, sys, signal -from test.test_support import verbose, TestFailed, TestSkipped +import pty +import os +import sys +import signal +from test.test_support import verbose, TestSkipped, run_unittest +import unittest TEST_STRING_1 = "I wish to buy a fish license.\n" TEST_STRING_2 = "For my pet fish, Eric.\n" @@ -11,6 +15,7 @@ def debug(msg): pass + def normalize_output(data): # Some operating systems do conversions on newline. We could possibly # fix that by doing the appropriate termios.tcsetattr()s. I couldn't @@ -32,116 +37,141 @@ return data + # Marginal testing of pty suite. Cannot do extensive 'do or fail' testing # because pty code is not too portable. +class PtyTest(unittest.TestCase): + def setUp(self): + # isatty() and close() can hang on some platforms. Set an alarm + # before running the test to make sure we don't hang forever. + self.old_alarm = signal.signal(signal.SIGALRM, self.handle_sig) + signal.alarm(10) + + def tearDown(self): + # remove alarm, restore old alarm handler + signal.alarm(0) + signal.signal(signal.SIGALRM, self.old_alarm) + + def handle_sig(self, sig, frame): + self.fail("isatty hung") + + def test_basic(self): + try: + debug("Calling master_open()") + master_fd, slave_name = pty.master_open() + debug("Got master_fd '%d', slave_name '%s'" % + (master_fd, slave_name)) + debug("Calling slave_open(%r)" % (slave_name,)) + slave_fd = pty.slave_open(slave_name) + debug("Got slave_fd '%d'" % slave_fd) + except OSError: + # " An optional feature could not be imported " ... ? + raise TestSkipped, "Pseudo-terminals (seemingly) not functional." + + self.assertTrue(os.isatty(slave_fd), 'slave_fd is not a tty') + + debug("Writing to slave_fd") + os.write(slave_fd, TEST_STRING_1) + s1 = os.read(master_fd, 1024) + self.assertEquals('I wish to buy a fish license.\n', + normalize_output(s1)) + + debug("Writing chunked output") + os.write(slave_fd, TEST_STRING_2[:5]) + os.write(slave_fd, TEST_STRING_2[5:]) + s2 = os.read(master_fd, 1024) + self.assertEquals('For my pet fish, Eric.\n', normalize_output(s2)) + + os.close(slave_fd) + os.close(master_fd) + + + def test_fork(self): + debug("calling pty.fork()") + pid, master_fd = pty.fork() + if pid == pty.CHILD: + # stdout should be connected to a tty. + if not os.isatty(1): + debug("Child's fd 1 is not a tty?!") + os._exit(3) + + # After pty.fork(), the child should already be a session leader. + # (on those systems that have that concept.) + debug("In child, calling os.setsid()") + try: + os.setsid() + except OSError: + # Good, we already were session leader + debug("Good: OSError was raised.") + pass + except AttributeError: + # Have pty, but not setsid()? + debug("No setsid() available?") + pass + except: + # We don't want this error to propagate, escaping the call to + # os._exit() and causing very peculiar behavior in the calling + # regrtest.py ! + # Note: could add traceback printing here. + debug("An unexpected error was raised.") + os._exit(1) + else: + debug("os.setsid() succeeded! (bad!)") + os._exit(2) + os._exit(4) + else: + debug("Waiting for child (%d) to finish." % pid) + # In verbose mode, we have to consume the debug output from the + # child or the child will block, causing this test to hang in the + # parent's waitpid() call. The child blocks after a + # platform-dependent amount of data is written to its fd. On + # Linux 2.6, it's 4000 bytes and the child won't block, but on OS + # X even the small writes in the child above will block it. Also + # on Linux, the read() will throw an OSError (input/output error) + # when it tries to read past the end of the buffer but the child's + # already exited, so catch and discard those exceptions. It's not + # worth checking for EIO. + while True: + try: + data = os.read(master_fd, 80) + except OSError: + break + if not data: + break + sys.stdout.write(data.replace('\r\n', '\n')) + + ##line = os.read(master_fd, 80) + ##lines = line.replace('\r\n', '\n').split('\n') + ##if False and lines != ['In child, calling os.setsid()', + ## 'Good: OSError was raised.', '']: + ## raise TestFailed("Unexpected output from child: %r" % line) + + (pid, status) = os.waitpid(pid, 0) + res = status >> 8 + debug("Child (%d) exited with status %d (%d)." % (pid, res, status)) + if res == 1: + self.fail("Child raised an unexpected exception in os.setsid()") + elif res == 2: + self.fail("pty.fork() failed to make child a session leader.") + elif res == 3: + self.fail("Child spawned by pty.fork() did not have a tty as stdout") + elif res != 4: + self.fail("pty.fork() failed for unknown reasons.") + + ##debug("Reading from master_fd now that the child has exited") + ##try: + ## s1 = os.read(master_fd, 1024) + ##except os.error: + ## pass + ##else: + ## raise TestFailed("Read from master_fd did not raise exception") + + os.close(master_fd) -def test_basic_pty(): - try: - debug("Calling master_open()") - master_fd, slave_name = pty.master_open() - debug("Got master_fd '%d', slave_name '%s'"%(master_fd, slave_name)) - debug("Calling slave_open(%r)"%(slave_name,)) - slave_fd = pty.slave_open(slave_name) - debug("Got slave_fd '%d'"%slave_fd) - except OSError: - # " An optional feature could not be imported " ... ? - raise TestSkipped, "Pseudo-terminals (seemingly) not functional." - - if not os.isatty(slave_fd): - raise TestFailed, "slave_fd is not a tty" - - debug("Writing to slave_fd") - os.write(slave_fd, TEST_STRING_1) - s1 = os.read(master_fd, 1024) - sys.stdout.write(normalize_output(s1)) - - debug("Writing chunked output") - os.write(slave_fd, TEST_STRING_2[:5]) - os.write(slave_fd, TEST_STRING_2[5:]) - s2 = os.read(master_fd, 1024) - sys.stdout.write(normalize_output(s2)) - - os.close(slave_fd) - os.close(master_fd) - -def handle_sig(sig, frame): - raise TestFailed, "isatty hung" - -# isatty() and close() can hang on some platforms -# set an alarm before running the test to make sure we don't hang forever -old_alarm = signal.signal(signal.SIGALRM, handle_sig) -signal.alarm(10) - -try: - test_basic_pty() -finally: - # remove alarm, restore old alarm handler - signal.alarm(0) - signal.signal(signal.SIGALRM, old_alarm) - -# basic pty passed. - -debug("calling pty.fork()") -pid, master_fd = pty.fork() -if pid == pty.CHILD: - # stdout should be connected to a tty. - if not os.isatty(1): - debug("Child's fd 1 is not a tty?!") - os._exit(3) - - # After pty.fork(), the child should already be a session leader. - # (on those systems that have that concept.) - debug("In child, calling os.setsid()") - try: - os.setsid() - except OSError: - # Good, we already were session leader - debug("Good: OSError was raised.") - pass - except AttributeError: - # Have pty, but not setsid() ? - debug("No setsid() available ?") - pass - except: - # We don't want this error to propagate, escaping the call to - # os._exit() and causing very peculiar behavior in the calling - # regrtest.py ! - # Note: could add traceback printing here. - debug("An unexpected error was raised.") - os._exit(1) - else: - debug("os.setsid() succeeded! (bad!)") - os._exit(2) - os._exit(4) -else: - debug("Waiting for child (%d) to finish."%pid) - ##line = os.read(master_fd, 80) - ##lines = line.replace('\r\n', '\n').split('\n') - ##if False and lines != ['In child, calling os.setsid()', - ## 'Good: OSError was raised.', '']: - ## raise TestFailed("Unexpected output from child: %r" % line) - - (pid, status) = os.waitpid(pid, 0) - res = status >> 8 - debug("Child (%d) exited with status %d (%d)."%(pid, res, status)) - if res == 1: - raise TestFailed, "Child raised an unexpected exception in os.setsid()" - elif res == 2: - raise TestFailed, "pty.fork() failed to make child a session leader." - elif res == 3: - raise TestFailed, "Child spawned by pty.fork() did not have a tty as stdout" - elif res != 4: - raise TestFailed, "pty.fork() failed for unknown reasons." - - ##debug("Reading from master_fd now that the child has exited") - ##try: - ## s1 = os.read(master_fd, 1024) - ##except os.error: - ## pass - ##else: - ## raise TestFailed("Read from master_fd did not raise exception") - + # pty.fork() passed. -os.close(master_fd) +def test_main(verbose=None): + run_unittest(PtyTest) -# pty.fork() passed. +if __name__ == "__main__": + test_main() Modified: python/branches/p3yk/Lib/test/test_pyexpat.py ============================================================================== --- python/branches/p3yk/Lib/test/test_pyexpat.py (original) +++ python/branches/p3yk/Lib/test/test_pyexpat.py Fri Apr 27 21:54:29 2007 @@ -1,108 +1,40 @@ -# Very simple test - Parse a file and print what happens - # XXX TypeErrors on calling handlers, or on bad return values from a # handler, are obscure and unhelpful. +import StringIO +import unittest + import pyexpat from xml.parsers import expat -from test.test_support import sortdict, TestFailed +from test.test_support import sortdict, run_unittest -class Outputter: - def StartElementHandler(self, name, attrs): - print('Start element:\n\t' + repr(name), sortdict(attrs)) - def EndElementHandler(self, name): - print('End element:\n\t' + repr(name)) +class SetAttributeTest(unittest.TestCase): + def setUp(self): + self.parser = expat.ParserCreate(namespace_separator='!') + self.set_get_pairs = [ + [0, 0], + [1, 1], + [2, 1], + [0, 0], + ] + + def test_returns_unicode(self): + for x, y in self.set_get_pairs: + self.parser.returns_unicode = x + self.assertEquals(self.parser.returns_unicode, y) + + def test_ordered_attributes(self): + for x, y in self.set_get_pairs: + self.parser.ordered_attributes = x + self.assertEquals(self.parser.ordered_attributes, y) + + def test_specified_attributes(self): + for x, y in self.set_get_pairs: + self.parser.specified_attributes = x + self.assertEquals(self.parser.specified_attributes, y) - def CharacterDataHandler(self, data): - data = data.strip() - if data: - print('Character data:') - print('\t' + repr(data)) - - def ProcessingInstructionHandler(self, target, data): - print('PI:\n\t' + repr(target), repr(data)) - - def StartNamespaceDeclHandler(self, prefix, uri): - print('NS decl:\n\t' + repr(prefix), repr(uri)) - - def EndNamespaceDeclHandler(self, prefix): - print('End of NS decl:\n\t' + repr(prefix)) - - def StartCdataSectionHandler(self): - print('Start of CDATA section') - - def EndCdataSectionHandler(self): - print('End of CDATA section') - - def CommentHandler(self, text): - print('Comment:\n\t' + repr(text)) - - def NotationDeclHandler(self, *args): - name, base, sysid, pubid = args - print('Notation declared:', args) - - def UnparsedEntityDeclHandler(self, *args): - entityName, base, systemId, publicId, notationName = args - print('Unparsed entity decl:\n\t' + str(args)) - - def NotStandaloneHandler(self, userData): - print('Not standalone') - return 1 - - def ExternalEntityRefHandler(self, *args): - context, base, sysId, pubId = args - print('External entity ref:', args[1:]) - return 1 - - def DefaultHandler(self, userData): - pass - - def DefaultHandlerExpand(self, userData): - pass - - -def confirm(ok): - if ok: - print("OK.") - else: - print("Not OK.") - -out = Outputter() -parser = expat.ParserCreate(namespace_separator='!') - -# Test getting/setting returns_unicode -parser.returns_unicode = 0; confirm(parser.returns_unicode == 0) -parser.returns_unicode = 1; confirm(parser.returns_unicode == 1) -parser.returns_unicode = 2; confirm(parser.returns_unicode == 1) -parser.returns_unicode = 0; confirm(parser.returns_unicode == 0) - -# Test getting/setting ordered_attributes -parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0) -parser.ordered_attributes = 1; confirm(parser.ordered_attributes == 1) -parser.ordered_attributes = 2; confirm(parser.ordered_attributes == 1) -parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0) - -# Test getting/setting specified_attributes -parser.specified_attributes = 0; confirm(parser.specified_attributes == 0) -parser.specified_attributes = 1; confirm(parser.specified_attributes == 1) -parser.specified_attributes = 2; confirm(parser.specified_attributes == 1) -parser.specified_attributes = 0; confirm(parser.specified_attributes == 0) - -HANDLER_NAMES = [ - 'StartElementHandler', 'EndElementHandler', - 'CharacterDataHandler', 'ProcessingInstructionHandler', - 'UnparsedEntityDeclHandler', 'NotationDeclHandler', - 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler', - 'CommentHandler', 'StartCdataSectionHandler', - 'EndCdataSectionHandler', - 'DefaultHandler', 'DefaultHandlerExpand', - #'NotStandaloneHandler', - 'ExternalEntityRefHandler' - ] -for name in HANDLER_NAMES: - setattr(parser, name, getattr(out, name)) data = '''\ @@ -126,108 +58,228 @@ ''' -# Produce UTF-8 output -parser.returns_unicode = 0 -try: - parser.Parse(data, 1) -except expat.error: - print('** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)) - print('** Line', parser.ErrorLineNumber) - print('** Column', parser.ErrorColumnNumber) - print('** Byte', parser.ErrorByteIndex) - -# Try the parse again, this time producing Unicode output -parser = expat.ParserCreate(namespace_separator='!') -parser.returns_unicode = 1 - -for name in HANDLER_NAMES: - setattr(parser, name, getattr(out, name)) -try: - parser.Parse(data, 1) -except expat.error: - print('** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)) - print('** Line', parser.ErrorLineNumber) - print('** Column', parser.ErrorColumnNumber) - print('** Byte', parser.ErrorByteIndex) - -# Try parsing a file -parser = expat.ParserCreate(namespace_separator='!') -parser.returns_unicode = 1 -for name in HANDLER_NAMES: - setattr(parser, name, getattr(out, name)) -import StringIO -file = StringIO.StringIO(data) -try: - parser.ParseFile(file) -except expat.error: - print('** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)) - print('** Line', parser.ErrorLineNumber) - print('** Column', parser.ErrorColumnNumber) - print('** Byte', parser.ErrorByteIndex) - - -# Tests that make sure we get errors when the namespace_separator value -# is illegal, and that we don't for good values: -print() -print("Testing constructor for proper handling of namespace_separator values:") -expat.ParserCreate() -expat.ParserCreate(namespace_separator=None) -expat.ParserCreate(namespace_separator=' ') -print("Legal values tested o.k.") -try: - expat.ParserCreate(namespace_separator=42) -except TypeError as e: - print("Caught expected TypeError:") - print(e) -else: - print("Failed to catch expected TypeError.") - -try: - expat.ParserCreate(namespace_separator='too long') -except ValueError as e: - print("Caught expected ValueError:") - print(e) -else: - print("Failed to catch expected ValueError.") - -# ParserCreate() needs to accept a namespace_separator of zero length -# to satisfy the requirements of RDF applications that are required -# to simply glue together the namespace URI and the localname. Though -# considered a wart of the RDF specifications, it needs to be supported. -# -# See XML-SIG mailing list thread starting with -# http://mail.python.org/pipermail/xml-sig/2001-April/005202.html -# -expat.ParserCreate(namespace_separator='') # too short - -# Test the interning machinery. -p = expat.ParserCreate() -L = [] -def collector(name, *args): - L.append(name) -p.StartElementHandler = collector -p.EndElementHandler = collector -p.Parse(" ", 1) -tag = L[0] -if len(L) != 6: - print("L should only contain 6 entries; found", len(L)) -for entry in L: - if tag is not entry: - print("expected L to contain many references to the same string", end=' ') - print("(it didn't)") - print("L =", repr(L)) - break +# Produce UTF-8 output +class ParseTest(unittest.TestCase): + class Outputter: + def __init__(self): + self.out = [] + + def StartElementHandler(self, name, attrs): + self.out.append('Start element: ' + repr(name) + ' ' + + sortdict(attrs)) + + def EndElementHandler(self, name): + self.out.append('End element: ' + repr(name)) + + def CharacterDataHandler(self, data): + data = data.strip() + if data: + self.out.append('Character data: ' + repr(data)) + + def ProcessingInstructionHandler(self, target, data): + self.out.append('PI: ' + repr(target) + ' ' + repr(data)) + + def StartNamespaceDeclHandler(self, prefix, uri): + self.out.append('NS decl: ' + repr(prefix) + ' ' + repr(uri)) + + def EndNamespaceDeclHandler(self, prefix): + self.out.append('End of NS decl: ' + repr(prefix)) + + def StartCdataSectionHandler(self): + self.out.append('Start of CDATA section') + + def EndCdataSectionHandler(self): + self.out.append('End of CDATA section') + + def CommentHandler(self, text): + self.out.append('Comment: ' + repr(text)) + + def NotationDeclHandler(self, *args): + name, base, sysid, pubid = args + self.out.append('Notation declared: %s' %(args,)) + + def UnparsedEntityDeclHandler(self, *args): + entityName, base, systemId, publicId, notationName = args + self.out.append('Unparsed entity decl: %s' %(args,)) + + def NotStandaloneHandler(self, userData): + self.out.append('Not standalone') + return 1 + + def ExternalEntityRefHandler(self, *args): + context, base, sysId, pubId = args + self.out.append('External entity ref: %s' %(args[1:],)) + return 1 + + def DefaultHandler(self, userData): + pass + + def DefaultHandlerExpand(self, userData): + pass + + handler_names = [ + 'StartElementHandler', 'EndElementHandler', + 'CharacterDataHandler', 'ProcessingInstructionHandler', + 'UnparsedEntityDeclHandler', 'NotationDeclHandler', + 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler', + 'CommentHandler', 'StartCdataSectionHandler', + 'EndCdataSectionHandler', + 'DefaultHandler', 'DefaultHandlerExpand', + #'NotStandaloneHandler', + 'ExternalEntityRefHandler' + ] + + def test_utf8(self): + + out = self.Outputter() + parser = expat.ParserCreate(namespace_separator='!') + for name in self.handler_names: + setattr(parser, name, getattr(out, name)) + parser.returns_unicode = 0 + parser.Parse(data, 1) + + # Verify output + op = out.out + self.assertEquals(op[0], 'PI: \'xml-stylesheet\' \'href="stylesheet.css"\'') + self.assertEquals(op[1], "Comment: ' comment data '") + self.assertEquals(op[2], "Notation declared: ('notation', None, 'notation.jpeg', None)") + self.assertEquals(op[3], "Unparsed entity decl: ('unparsed_entity', None, 'entity.file', None, 'notation')") + self.assertEquals(op[4], "Start element: 'root' {'attr1': 'value1', 'attr2': 'value2\\xe1\\xbd\\x80'}") + self.assertEquals(op[5], "NS decl: 'myns' 'http://www.python.org/namespace'") + self.assertEquals(op[6], "Start element: 'http://www.python.org/namespace!subelement' {}") + self.assertEquals(op[7], "Character data: 'Contents of subelements'") + self.assertEquals(op[8], "End element: 'http://www.python.org/namespace!subelement'") + self.assertEquals(op[9], "End of NS decl: 'myns'") + self.assertEquals(op[10], "Start element: 'sub2' {}") + self.assertEquals(op[11], 'Start of CDATA section') + self.assertEquals(op[12], "Character data: 'contents of CDATA section'") + self.assertEquals(op[13], 'End of CDATA section') + self.assertEquals(op[14], "End element: 'sub2'") + self.assertEquals(op[15], "External entity ref: (None, 'entity.file', None)") + self.assertEquals(op[16], "End element: 'root'") + + def test_unicode(self): + # Try the parse again, this time producing Unicode output + out = self.Outputter() + parser = expat.ParserCreate(namespace_separator='!') + parser.returns_unicode = 1 + for name in self.handler_names: + setattr(parser, name, getattr(out, name)) + + parser.Parse(data, 1) + + op = out.out + self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'') + self.assertEquals(op[1], "Comment: u' comment data '") + self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)") + self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')") + self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}") + self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'") + self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}") + self.assertEquals(op[7], "Character data: u'Contents of subelements'") + self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'") + self.assertEquals(op[9], "End of NS decl: u'myns'") + self.assertEquals(op[10], "Start element: u'sub2' {}") + self.assertEquals(op[11], 'Start of CDATA section') + self.assertEquals(op[12], "Character data: u'contents of CDATA section'") + self.assertEquals(op[13], 'End of CDATA section') + self.assertEquals(op[14], "End element: u'sub2'") + self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)") + self.assertEquals(op[16], "End element: u'root'") + + def test_parse_file(self): + # Try parsing a file + out = self.Outputter() + parser = expat.ParserCreate(namespace_separator='!') + parser.returns_unicode = 1 + for name in self.handler_names: + setattr(parser, name, getattr(out, name)) + file = StringIO.StringIO(data) + + parser.ParseFile(file) + + op = out.out + self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'') + self.assertEquals(op[1], "Comment: u' comment data '") + self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)") + self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')") + self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}") + self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'") + self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}") + self.assertEquals(op[7], "Character data: u'Contents of subelements'") + self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'") + self.assertEquals(op[9], "End of NS decl: u'myns'") + self.assertEquals(op[10], "Start element: u'sub2' {}") + self.assertEquals(op[11], 'Start of CDATA section') + self.assertEquals(op[12], "Character data: u'contents of CDATA section'") + self.assertEquals(op[13], 'End of CDATA section') + self.assertEquals(op[14], "End element: u'sub2'") + self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)") + self.assertEquals(op[16], "End element: u'root'") + + +class NamespaceSeparatorTest(unittest.TestCase): + def test_legal(self): + # Tests that make sure we get errors when the namespace_separator value + # is illegal, and that we don't for good values: + expat.ParserCreate() + expat.ParserCreate(namespace_separator=None) + expat.ParserCreate(namespace_separator=' ') + + def test_illegal(self): + try: + expat.ParserCreate(namespace_separator=42) + self.fail() + except TypeError as e: + self.assertEquals(str(e), + 'ParserCreate() argument 2 must be string or None, not int') + + try: + expat.ParserCreate(namespace_separator='too long') + self.fail() + except ValueError as e: + self.assertEquals(str(e), + 'namespace_separator must be at most one character, omitted, or None') + + def test_zero_length(self): + # ParserCreate() needs to accept a namespace_separator of zero length + # to satisfy the requirements of RDF applications that are required + # to simply glue together the namespace URI and the localname. Though + # considered a wart of the RDF specifications, it needs to be supported. + # + # See XML-SIG mailing list thread starting with + # http://mail.python.org/pipermail/xml-sig/2001-April/005202.html + # + expat.ParserCreate(namespace_separator='') # too short + + +class InterningTest(unittest.TestCase): + def test(self): + # Test the interning machinery. + p = expat.ParserCreate() + L = [] + def collector(name, *args): + L.append(name) + p.StartElementHandler = collector + p.EndElementHandler = collector + p.Parse(" ", 1) + tag = L[0] + self.assertEquals(len(L), 6) + for entry in L: + # L should have the same string repeated over and over. + self.assertTrue(tag is entry) -# Tests of the buffer_text attribute. -import sys -class TextCollector: - def __init__(self, parser): +class BufferTextTest(unittest.TestCase): + def setUp(self): self.stuff = [] + self.parser = expat.ParserCreate() + self.parser.buffer_text = 1 + self.parser.CharacterDataHandler = self.CharacterDataHandler def check(self, expected, label): - require(self.stuff == expected, + self.assertEquals(self.stuff, expected, "%s\nstuff = %r\nexpected = %r" % (label, self.stuff, map(unicode, expected))) @@ -238,9 +290,9 @@ self.stuff.append("<%s>" % name) bt = attrs.get("buffer-text") if bt == "yes": - parser.buffer_text = 1 + self.parser.buffer_text = 1 elif bt == "no": - parser.buffer_text = 0 + self.parser.buffer_text = 0 def EndElementHandler(self, name): self.stuff.append("" % name) @@ -248,95 +300,91 @@ def CommentHandler(self, data): self.stuff.append("" % data) -def require(cond, label): - # similar to confirm(), but no extraneous output - if not cond: - raise TestFailed(label) - -def setup(handlers=[]): - parser = expat.ParserCreate() - require(not parser.buffer_text, - "buffer_text not disabled by default") - parser.buffer_text = 1 - handler = TextCollector(parser) - parser.CharacterDataHandler = handler.CharacterDataHandler - for name in handlers: - setattr(parser, name, getattr(handler, name)) - return parser, handler - -parser, handler = setup() -require(parser.buffer_text, - "text buffering either not acknowledged or not enabled") -parser.Parse("123", 1) -handler.check(["123"], - "buffered text not properly collapsed") - -# XXX This test exposes more detail of Expat's text chunking than we -# XXX like, but it tests what we need to concisely. -parser, handler = setup(["StartElementHandler"]) -parser.Parse("12\n34\n5", 1) -handler.check(["", "1", "", "2", "\n", "3", "", "4\n5"], - "buffering control not reacting as expected") - -parser, handler = setup() -parser.Parse("1<2> \n 3", 1) -handler.check(["1<2> \n 3"], - "buffered text not properly collapsed") - -parser, handler = setup(["StartElementHandler"]) -parser.Parse("123", 1) -handler.check(["", "1", "", "2", "", "3"], - "buffered text not properly split") - -parser, handler = setup(["StartElementHandler", "EndElementHandler"]) -parser.CharacterDataHandler = None -parser.Parse("123", 1) -handler.check(["", "", "", "", "", ""], - "huh?") - -parser, handler = setup(["StartElementHandler", "EndElementHandler"]) -parser.Parse("123", 1) -handler.check(["", "1", "", "", "2", "", "", "3", ""], - "huh?") - -parser, handler = setup(["CommentHandler", "EndElementHandler", - "StartElementHandler"]) -parser.Parse("12345 ", 1) -handler.check(["", "1", "", "", "2", "", "", "345", ""], - "buffered text not properly split") - -parser, handler = setup(["CommentHandler", "EndElementHandler", - "StartElementHandler"]) -parser.Parse("12345 ", 1) -handler.check(["", "1", "", "", "2", "", "", "3", - "", "4", "", "5", ""], - "buffered text not properly split") + def setHandlers(self, handlers=[]): + for name in handlers: + setattr(self.parser, name, getattr(self, name)) + + def test_default_to_disabled(self): + parser = expat.ParserCreate() + self.assertFalse(parser.buffer_text) + + def test_buffering_enabled(self): + # Make sure buffering is turned on + self.assertTrue(self.parser.buffer_text) + self.parser.Parse("123", 1) + self.assertEquals(self.stuff, ['123'], + "buffered text not properly collapsed") + + def test1(self): + # XXX This test exposes more detail of Expat's text chunking than we + # XXX like, but it tests what we need to concisely. + self.setHandlers(["StartElementHandler"]) + self.parser.Parse("12\n34\n5", 1) + self.assertEquals(self.stuff, + ["", "1", "", "2", "\n", "3", "", "4\n5"], + "buffering control not reacting as expected") + + def test2(self): + self.parser.Parse("1<2> \n 3", 1) + self.assertEquals(self.stuff, ["1<2> \n 3"], + "buffered text not properly collapsed") + + def test3(self): + self.setHandlers(["StartElementHandler"]) + self.parser.Parse("123", 1) + self.assertEquals(self.stuff, ["", "1", "", "2", "", "3"], + "buffered text not properly split") + + def test4(self): + self.setHandlers(["StartElementHandler", "EndElementHandler"]) + self.parser.CharacterDataHandler = None + self.parser.Parse("123", 1) + self.assertEquals(self.stuff, + ["", "", "", "", "", ""]) + + def test5(self): + self.setHandlers(["StartElementHandler", "EndElementHandler"]) + self.parser.Parse("123", 1) + self.assertEquals(self.stuff, + ["", "1", "", "", "2", "", "", "3", ""]) + + def test6(self): + self.setHandlers(["CommentHandler", "EndElementHandler", + "StartElementHandler"]) + self.parser.Parse("12345 ", 1) + self.assertEquals(self.stuff, + ["", "1", "", "", "2", "", "", "345", ""], + "buffered text not properly split") + + def test7(self): + self.setHandlers(["CommentHandler", "EndElementHandler", + "StartElementHandler"]) + self.parser.Parse("12345 ", 1) + self.assertEquals(self.stuff, + ["", "1", "", "", "2", "", "", "3", + "", "4", "", "5", ""], + "buffered text not properly split") + # Test handling of exception from callback: -def StartElementHandler(name, attrs): - raise RuntimeError(name) +class HandlerExceptionTest(unittest.TestCase): + def StartElementHandler(self, name, attrs): + raise RuntimeError(name) -parser = expat.ParserCreate() -parser.StartElementHandler = StartElementHandler + def test(self): + parser = expat.ParserCreate() + parser.StartElementHandler = self.StartElementHandler + try: + parser.Parse("", 1) + self.fail() + except RuntimeError as e: + self.assertEquals(e.args[0], 'a', + "Expected RuntimeError for element 'a', but" + \ + " found %r" % e.args[0]) -try: - parser.Parse("", 1) -except RuntimeError as e: - if e.args[0] != "a": - print("Expected RuntimeError for element 'a'; found %r" % e.args[0]) -else: - print("Expected RuntimeError for 'a'") # Test Current* members: -class PositionTest: - - def __init__(self, expected_list, parser): - self.parser = parser - self.parser.StartElementHandler = self.StartElementHandler - self.parser.EndElementHandler = self.EndElementHandler - self.expected_list = expected_list - self.upto = 0 - +class PositionTest(unittest.TestCase): def StartElementHandler(self, name, attrs): self.check_pos('s') @@ -348,41 +396,54 @@ self.parser.CurrentByteIndex, self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber) - require(self.upto < len(self.expected_list), - 'too many parser events') + self.assertTrue(self.upto < len(self.expected_list), + 'too many parser events') expected = self.expected_list[self.upto] - require(pos == expected, - 'expected position %s, got %s' % (expected, pos)) + self.assertEquals(pos, expected, + 'Expected position %s, got position %s' %(pos, expected)) self.upto += 1 + def test(self): + self.parser = expat.ParserCreate() + self.parser.StartElementHandler = self.StartElementHandler + self.parser.EndElementHandler = self.EndElementHandler + self.upto = 0 + self.expected_list = [('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2), + ('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)] + + xml = '\n \n \n \n' + self.parser.Parse(xml, 1) + + +class sf1296433Test(unittest.TestCase): + def test_parse_only_xml_data(self): + # http://python.org/sf/1296433 + # + xml = "%s" % ('a' * 1025) + # this one doesn't crash + #xml = "%s" % ('a' * 10000) + + class SpecificException(Exception): + pass + + def handler(text): + raise SpecificException + + parser = expat.ParserCreate() + parser.CharacterDataHandler = handler + + self.assertRaises(Exception, parser.Parse, xml) + -parser = expat.ParserCreate() -handler = PositionTest([('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2), - ('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)], - parser) -parser.Parse(''' - - - -''', 1) - - -def test_parse_only_xml_data(): - # http://python.org/sf/1296433 - # - xml = "%s" % ('a' * 1025) - # this one doesn't crash - #xml = "%s" % ('a' * 10000) - - def handler(text): - raise Exception - - parser = expat.ParserCreate() - parser.CharacterDataHandler = handler - - try: - parser.Parse(xml) - except: - pass +def test_main(): + run_unittest(SetAttributeTest, + ParseTest, + NamespaceSeparatorTest, + InterningTest, + BufferTextTest, + HandlerExceptionTest, + PositionTest, + sf1296433Test) -test_parse_only_xml_data() +if __name__ == "__main__": + test_main() Modified: python/branches/p3yk/Lib/test/test_re.py ============================================================================== --- python/branches/p3yk/Lib/test/test_re.py (original) +++ python/branches/p3yk/Lib/test/test_re.py Fri Apr 27 21:54:29 2007 @@ -1,7 +1,7 @@ import sys sys.path = ['.'] + sys.path -from test.test_support import verbose, run_unittest +from test.test_support import verbose, run_unittest, guard_warnings_filter import re from re import Scanner import sys, os, traceback @@ -418,6 +418,12 @@ pass # cPickle not found -- skip it else: self.pickle_test(cPickle) + # old pickles expect the _compile() reconstructor in sre module + import warnings + with guard_warnings_filter(): + warnings.filterwarnings("ignore", "The sre module is deprecated", + DeprecationWarning) + from sre import _compile def pickle_test(self, pickle): oldpat = re.compile('a(?:b|(c|e){1,2}?|d)+?(.)') @@ -599,6 +605,13 @@ self.assertEqual(next(iter).span(), (4, 4)) self.assertRaises(StopIteration, next, iter) + def test_empty_array(self): + # SF buf 1647541 + import array + for typecode in 'cbBuhHiIlLfd': + a = array.array(typecode) + self.assertEqual(re.compile("bla").match(a), None) + self.assertEqual(re.compile("").match(a).groups(), ()) def run_re_tests(): from test.re_tests import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR Modified: python/branches/p3yk/Lib/test/test_robotparser.py ============================================================================== --- python/branches/p3yk/Lib/test/test_robotparser.py (original) +++ python/branches/p3yk/Lib/test/test_robotparser.py Fri Apr 27 21:54:29 2007 @@ -135,8 +135,8 @@ RobotTest(7, doc, good, bad) def test_main(): - test_support.run_suite(tests) + test_support.run_unittest(tests) if __name__=='__main__': test_support.Verbose = 1 - test_support.run_suite(tests) + test_main() Modified: python/branches/p3yk/Lib/test/test_sax.py ============================================================================== --- python/branches/p3yk/Lib/test/test_sax.py (original) +++ python/branches/p3yk/Lib/test/test_sax.py Fri Apr 27 21:54:29 2007 @@ -13,26 +13,66 @@ from xml.sax.expatreader import create_parser from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl from cStringIO import StringIO -from test.test_support import verify, verbose, TestFailed, findfile +from test.test_support import findfile, run_unittest +import unittest import os -# ===== Utilities - -tests = 0 -failures = [] - -def confirm(outcome, name): - global tests +ns_uri = "http://www.python.org/xml-ns/saxtest/" - tests = tests + 1 - if outcome: - if verbose: - print("Passed", name) - else: - failures.append(name) +class XmlTestBase(unittest.TestCase): + def verify_empty_attrs(self, attrs): + self.assertRaises(KeyError, attrs.getValue, "attr") + self.assertRaises(KeyError, attrs.getValueByQName, "attr") + self.assertRaises(KeyError, attrs.getNameByQName, "attr") + self.assertRaises(KeyError, attrs.getQNameByName, "attr") + self.assertRaises(KeyError, attrs.__getitem__, "attr") + self.assertEquals(attrs.getLength(), 0) + self.assertEquals(attrs.getNames(), []) + self.assertEquals(attrs.getQNames(), []) + self.assertEquals(len(attrs), 0) + self.assertFalse("attr" in attrs) + self.assertEquals(list(attrs.keys()), []) + self.assertEquals(attrs.get("attrs"), None) + self.assertEquals(attrs.get("attrs", 25), 25) + self.assertEquals(list(attrs.items()), []) + self.assertEquals(list(attrs.values()), []) + + def verify_empty_nsattrs(self, attrs): + self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr")) + self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr") + self.assertRaises(KeyError, attrs.getNameByQName, "ns:attr") + self.assertRaises(KeyError, attrs.getQNameByName, (ns_uri, "attr")) + self.assertRaises(KeyError, attrs.__getitem__, (ns_uri, "attr")) + self.assertEquals(attrs.getLength(), 0) + self.assertEquals(attrs.getNames(), []) + self.assertEquals(attrs.getQNames(), []) + self.assertEquals(len(attrs), 0) + self.assertFalse((ns_uri, "attr") in attrs) + self.assertEquals(list(attrs.keys()), []) + self.assertEquals(attrs.get((ns_uri, "attr")), None) + self.assertEquals(attrs.get((ns_uri, "attr"), 25), 25) + self.assertEquals(list(attrs.items()), []) + self.assertEquals(list(attrs.values()), []) + + def verify_attrs_wattr(self, attrs): + self.assertEquals(attrs.getLength(), 1) + self.assertEquals(attrs.getNames(), ["attr"]) + self.assertEquals(attrs.getQNames(), ["attr"]) + self.assertEquals(len(attrs), 1) + self.assertTrue("attr" in attrs) + self.assertEquals(list(attrs.keys()), ["attr"]) + self.assertEquals(attrs.get("attr"), "val") + self.assertEquals(attrs.get("attr", 25), "val") + self.assertEquals(list(attrs.items()), [("attr", "val")]) + self.assertEquals(list(attrs.values()), ["val"]) + self.assertEquals(attrs.getValue("attr"), "val") + self.assertEquals(attrs.getValueByQName("attr"), "val") + self.assertEquals(attrs.getNameByQName("attr"), "attr") + self.assertEquals(attrs["attr"], "val") + self.assertEquals(attrs.getQNameByName("attr"), "attr") -def test_make_parser2(): - try: +class MakeParserTest(unittest.TestCase): + def test_make_parser2(self): # Creating parsers several times in a row should succeed. # Testing this because there have been failures of this kind # before. @@ -48,10 +88,6 @@ p = make_parser() from xml.sax import make_parser p = make_parser() - except: - return 0 - else: - return p # =========================================================================== @@ -60,215 +96,214 @@ # # =========================================================================== -# ===== escape - -def test_escape_basic(): - return escape("Donald Duck & Co") == "Donald Duck & Co" - -def test_escape_all(): - return escape("") == "<Donald Duck & Co>" - -def test_escape_extra(): - return escape("Hei p? deg", {"?" : "å"}) == "Hei på deg" - -# ===== unescape - -def test_unescape_basic(): - return unescape("Donald Duck & Co") == "Donald Duck & Co" - -def test_unescape_all(): - return unescape("<Donald Duck & Co>") == "" - -def test_unescape_extra(): - return unescape("Hei p? deg", {"?" : "å"}) == "Hei på deg" - -def test_unescape_amp_extra(): - return unescape("&foo;", {"&foo;": "splat"}) == "&foo;" +class SaxutilsTest(unittest.TestCase): + # ===== escape + def test_escape_basic(self): + self.assertEquals(escape("Donald Duck & Co"), "Donald Duck & Co") + + def test_escape_all(self): + self.assertEquals(escape(""), + "<Donald Duck & Co>") + + def test_escape_extra(self): + self.assertEquals(escape("Hei p? deg", {"?" : "å"}), + "Hei på deg") + + # ===== unescape + def test_unescape_basic(self): + self.assertEquals(unescape("Donald Duck & Co"), "Donald Duck & Co") + + def test_unescape_all(self): + self.assertEquals(unescape("<Donald Duck & Co>"), + "") + + def test_unescape_extra(self): + self.assertEquals(unescape("Hei p? deg", {"?" : "å"}), + "Hei på deg") + + def test_unescape_amp_extra(self): + self.assertEquals(unescape("&foo;", {"&foo;": "splat"}), "&foo;") + + # ===== quoteattr + def test_quoteattr_basic(self): + self.assertEquals(quoteattr("Donald Duck & Co"), + '"Donald Duck & Co"') + + def test_single_quoteattr(self): + self.assertEquals(quoteattr('Includes "double" quotes'), + '\'Includes "double" quotes\'') + + def test_double_quoteattr(self): + self.assertEquals(quoteattr("Includes 'single' quotes"), + "\"Includes 'single' quotes\"") + + def test_single_double_quoteattr(self): + self.assertEquals(quoteattr("Includes 'single' and \"double\" quotes"), + "\"Includes 'single' and "double" quotes\"") -# ===== quoteattr - -def test_quoteattr_basic(): - return quoteattr("Donald Duck & Co") == '"Donald Duck & Co"' - -def test_single_quoteattr(): - return (quoteattr('Includes "double" quotes') - == '\'Includes "double" quotes\'') - -def test_double_quoteattr(): - return (quoteattr("Includes 'single' quotes") - == "\"Includes 'single' quotes\"") - -def test_single_double_quoteattr(): - return (quoteattr("Includes 'single' and \"double\" quotes") - == "\"Includes 'single' and "double" quotes\"") - -# ===== make_parser - -def test_make_parser(): - try: + # ===== make_parser + def test_make_parser(self): # Creating a parser should succeed - it should fall back # to the expatreader p = make_parser(['xml.parsers.no_such_parser']) - except: - return 0 - else: - return p # ===== XMLGenerator start = '\n' -def test_xmlgen_basic(): - result = StringIO() - gen = XMLGenerator(result) - gen.startDocument() - gen.startElement("doc", {}) - gen.endElement("doc") - gen.endDocument() - - return result.getvalue() == start + "" - -def test_xmlgen_content(): - result = StringIO() - gen = XMLGenerator(result) - - gen.startDocument() - gen.startElement("doc", {}) - gen.characters("huhei") - gen.endElement("doc") - gen.endDocument() - - return result.getvalue() == start + "huhei" - -def test_xmlgen_pi(): - result = StringIO() - gen = XMLGenerator(result) - - gen.startDocument() - gen.processingInstruction("test", "data") - gen.startElement("doc", {}) - gen.endElement("doc") - gen.endDocument() - - return result.getvalue() == start + "" - -def test_xmlgen_content_escape(): - result = StringIO() - gen = XMLGenerator(result) - - gen.startDocument() - gen.startElement("doc", {}) - gen.characters("<huhei&" - -def test_xmlgen_attr_escape(): - result = StringIO() - gen = XMLGenerator(result) - - gen.startDocument() - gen.startElement("doc", {"a": '"'}) - gen.startElement("e", {"a": "'"}) - gen.endElement("e") - gen.startElement("e", {"a": "'\""}) - gen.endElement("e") - gen.startElement("e", {"a": "\n\r\t"}) - gen.endElement("e") - gen.endElement("doc") - gen.endDocument() - - return result.getvalue() == start + ("" - "" - "") - -def test_xmlgen_ignorable(): - result = StringIO() - gen = XMLGenerator(result) - - gen.startDocument() - gen.startElement("doc", {}) - gen.ignorableWhitespace(" ") - gen.endElement("doc") - gen.endDocument() +class XmlgenTest(unittest.TestCase): + def test_xmlgen_basic(self): + result = StringIO() + gen = XMLGenerator(result) + gen.startDocument() + gen.startElement("doc", {}) + gen.endElement("doc") + gen.endDocument() + + self.assertEquals(result.getvalue(), start + "") + + def test_xmlgen_content(self): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startElement("doc", {}) + gen.characters("huhei") + gen.endElement("doc") + gen.endDocument() + + self.assertEquals(result.getvalue(), start + "huhei") + + def test_xmlgen_pi(self): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.processingInstruction("test", "data") + gen.startElement("doc", {}) + gen.endElement("doc") + gen.endDocument() + + self.assertEquals(result.getvalue(), start + "") + + def test_xmlgen_content_escape(self): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startElement("doc", {}) + gen.characters("<huhei&") + + def test_xmlgen_attr_escape(self): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startElement("doc", {"a": '"'}) + gen.startElement("e", {"a": "'"}) + gen.endElement("e") + gen.startElement("e", {"a": "'\""}) + gen.endElement("e") + gen.startElement("e", {"a": "\n\r\t"}) + gen.endElement("e") + gen.endElement("doc") + gen.endDocument() + + self.assertEquals(result.getvalue(), start + + ("" + "" + "")) + + def test_xmlgen_ignorable(self): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startElement("doc", {}) + gen.ignorableWhitespace(" ") + gen.endElement("doc") + gen.endDocument() + + self.assertEquals(result.getvalue(), start + " ") + + def test_xmlgen_ns(self): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startPrefixMapping("ns1", ns_uri) + gen.startElementNS((ns_uri, "doc"), "ns1:doc", {}) + # add an unqualified name + gen.startElementNS((None, "udoc"), None, {}) + gen.endElementNS((None, "udoc"), None) + gen.endElementNS((ns_uri, "doc"), "ns1:doc") + gen.endPrefixMapping("ns1") + gen.endDocument() - return result.getvalue() == start + " " - -ns_uri = "http://www.python.org/xml-ns/saxtest/" - -def test_xmlgen_ns(): - result = StringIO() - gen = XMLGenerator(result) - - gen.startDocument() - gen.startPrefixMapping("ns1", ns_uri) - gen.startElementNS((ns_uri, "doc"), "ns1:doc", {}) - # add an unqualified name - gen.startElementNS((None, "udoc"), None, {}) - gen.endElementNS((None, "udoc"), None) - gen.endElementNS((ns_uri, "doc"), "ns1:doc") - gen.endPrefixMapping("ns1") - gen.endDocument() - - return result.getvalue() == start + \ + self.assertEquals(result.getvalue(), start + \ ('' % - ns_uri) + ns_uri)) -def test_1463026_1(): - result = StringIO() - gen = XMLGenerator(result) - - gen.startDocument() - gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'}) - gen.endElementNS((None, 'a'), 'a') - gen.endDocument() - - return result.getvalue() == start+'' - -def test_1463026_2(): - result = StringIO() - gen = XMLGenerator(result) - - gen.startDocument() - gen.startPrefixMapping(None, 'qux') - gen.startElementNS(('qux', 'a'), 'a', {}) - gen.endElementNS(('qux', 'a'), 'a') - gen.endPrefixMapping(None) - gen.endDocument() - - return result.getvalue() == start+'' - -def test_1463026_3(): - result = StringIO() - gen = XMLGenerator(result) - - gen.startDocument() - gen.startPrefixMapping('my', 'qux') - gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'}) - gen.endElementNS(('qux', 'a'), 'a') - gen.endPrefixMapping('my') - gen.endDocument() - - return result.getvalue() == start+'' - -# ===== Xmlfilterbase - -def test_filter_basic(): - result = StringIO() - gen = XMLGenerator(result) - filter = XMLFilterBase() - filter.setContentHandler(gen) - - filter.startDocument() - filter.startElement("doc", {}) - filter.characters("content") - filter.ignorableWhitespace(" ") - filter.endElement("doc") - filter.endDocument() + def test_1463026_1(self): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'}) + gen.endElementNS((None, 'a'), 'a') + gen.endDocument() + + self.assertEquals(result.getvalue(), start+'') + + def test_1463026_2(self): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startPrefixMapping(None, 'qux') + gen.startElementNS(('qux', 'a'), 'a', {}) + gen.endElementNS(('qux', 'a'), 'a') + gen.endPrefixMapping(None) + gen.endDocument() + + self.assertEquals(result.getvalue(), start+'') + + def test_1463026_3(self): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startPrefixMapping('my', 'qux') + gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'}) + gen.endElementNS(('qux', 'a'), 'a') + gen.endPrefixMapping('my') + gen.endDocument() + + self.assertEquals(result.getvalue(), + start+'') + + +class XMLFilterBaseTest(unittest.TestCase): + def test_filter_basic(self): + result = StringIO() + gen = XMLGenerator(result) + filter = XMLFilterBase() + filter.setContentHandler(gen) + + filter.startDocument() + filter.startElement("doc", {}) + filter.characters("content") + filter.ignorableWhitespace(" ") + filter.endElement("doc") + filter.endDocument() - return result.getvalue() == start + "content " + self.assertEquals(result.getvalue(), start + "content ") # =========================================================================== # @@ -276,229 +311,233 @@ # # =========================================================================== -# ===== XMLReader support +xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read() + +class ExpatReaderTest(XmlTestBase): -def test_expat_file(): - parser = create_parser() - result = StringIO() - xmlgen = XMLGenerator(result) + # ===== XMLReader support - parser.setContentHandler(xmlgen) - parser.parse(open(findfile("test"+os.extsep+"xml"))) + def test_expat_file(self): + parser = create_parser() + result = StringIO() + xmlgen = XMLGenerator(result) - return result.getvalue() == xml_test_out + parser.setContentHandler(xmlgen) + parser.parse(open(findfile("test"+os.extsep+"xml"))) -# ===== DTDHandler support + self.assertEquals(result.getvalue(), xml_test_out) -class TestDTDHandler: + # ===== DTDHandler support - def __init__(self): - self._notations = [] - self._entities = [] + class TestDTDHandler: - def notationDecl(self, name, publicId, systemId): - self._notations.append((name, publicId, systemId)) + def __init__(self): + self._notations = [] + self._entities = [] - def unparsedEntityDecl(self, name, publicId, systemId, ndata): - self._entities.append((name, publicId, systemId, ndata)) + def notationDecl(self, name, publicId, systemId): + self._notations.append((name, publicId, systemId)) -def test_expat_dtdhandler(): - parser = create_parser() - handler = TestDTDHandler() - parser.setDTDHandler(handler) + def unparsedEntityDecl(self, name, publicId, systemId, ndata): + self._entities.append((name, publicId, systemId, ndata)) - parser.feed('\n') - parser.feed(' \n') - parser.feed(']>\n') - parser.feed('') - parser.close() + def test_expat_dtdhandler(self): + parser = create_parser() + handler = self.TestDTDHandler() + parser.setDTDHandler(handler) - return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \ - handler._entities == [("img", None, "expat.gif", "GIF")] + parser.feed('\n') + parser.feed(' \n') + parser.feed(']>\n') + parser.feed('') + parser.close() -# ===== EntityResolver support + self.assertEquals(handler._notations, + [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)]) + self.assertEquals(handler._entities, [("img", None, "expat.gif", "GIF")]) -class TestEntityResolver: + # ===== EntityResolver support - def resolveEntity(self, publicId, systemId): - inpsrc = InputSource() - inpsrc.setByteStream(StringIO("")) - return inpsrc + class TestEntityResolver: -def test_expat_entityresolver(): - parser = create_parser() - parser.setEntityResolver(TestEntityResolver()) - result = StringIO() - parser.setContentHandler(XMLGenerator(result)) + def resolveEntity(self, publicId, systemId): + inpsrc = InputSource() + inpsrc.setByteStream(StringIO("")) + return inpsrc - parser.feed('\n') - parser.feed(']>\n') - parser.feed('&test;') - parser.close() + def test_expat_entityresolver(self): + parser = create_parser() + parser.setEntityResolver(self.TestEntityResolver()) + result = StringIO() + parser.setContentHandler(XMLGenerator(result)) - return result.getvalue() == start + "" + parser.feed('\n') + parser.feed(']>\n') + parser.feed('&test;') + parser.close() -# ===== Attributes support + self.assertEquals(result.getvalue(), start + + "") -class AttrGatherer(ContentHandler): + # ===== Attributes support - def startElement(self, name, attrs): - self._attrs = attrs + class AttrGatherer(ContentHandler): - def startElementNS(self, name, qname, attrs): - self._attrs = attrs + def startElement(self, name, attrs): + self._attrs = attrs -def test_expat_attrs_empty(): - parser = create_parser() - gather = AttrGatherer() - parser.setContentHandler(gather) + def startElementNS(self, name, qname, attrs): + self._attrs = attrs - parser.feed("") - parser.close() + def test_expat_attrs_empty(self): + parser = create_parser() + gather = self.AttrGatherer() + parser.setContentHandler(gather) - return verify_empty_attrs(gather._attrs) + parser.feed("") + parser.close() -def test_expat_attrs_wattr(): - parser = create_parser() - gather = AttrGatherer() - parser.setContentHandler(gather) + self.verify_empty_attrs(gather._attrs) - parser.feed("") - parser.close() + def test_expat_attrs_wattr(self): + parser = create_parser() + gather = self.AttrGatherer() + parser.setContentHandler(gather) - return verify_attrs_wattr(gather._attrs) + parser.feed("") + parser.close() -def test_expat_nsattrs_empty(): - parser = create_parser(1) - gather = AttrGatherer() - parser.setContentHandler(gather) + self.verify_attrs_wattr(gather._attrs) - parser.feed("") - parser.close() + def test_expat_nsattrs_empty(self): + parser = create_parser(1) + gather = self.AttrGatherer() + parser.setContentHandler(gather) - return verify_empty_nsattrs(gather._attrs) + parser.feed("") + parser.close() -def test_expat_nsattrs_wattr(): - parser = create_parser(1) - gather = AttrGatherer() - parser.setContentHandler(gather) + self.verify_empty_nsattrs(gather._attrs) - parser.feed("" % ns_uri) - parser.close() + def test_expat_nsattrs_wattr(self): + parser = create_parser(1) + gather = self.AttrGatherer() + parser.setContentHandler(gather) - attrs = gather._attrs + parser.feed("" % ns_uri) + parser.close() - return attrs.getLength() == 1 and \ - attrs.getNames() == [(ns_uri, "attr")] and \ - (attrs.getQNames() == [] or attrs.getQNames() == ["ns:attr"]) and \ - len(attrs) == 1 and \ - (ns_uri, "attr") in attrs and \ - list(attrs.keys()) == [(ns_uri, "attr")] and \ - attrs.get((ns_uri, "attr")) == "val" and \ - attrs.get((ns_uri, "attr"), 25) == "val" and \ - list(attrs.items()) == [((ns_uri, "attr"), "val")] and \ - list(attrs.values()) == ["val"] and \ - attrs.getValue((ns_uri, "attr")) == "val" and \ - attrs[(ns_uri, "attr")] == "val" + attrs = gather._attrs -# ===== InputSource support + self.assertEquals(attrs.getLength(), 1) + self.assertEquals(attrs.getNames(), [(ns_uri, "attr")]) + self.assertTrue((attrs.getQNames() == [] or + attrs.getQNames() == ["ns:attr"])) + self.assertEquals(len(attrs), 1) + self.assertTrue((ns_uri, "attr") in attrs) + self.assertEquals(attrs.get((ns_uri, "attr")), "val") + self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val") + self.assertEquals(list(attrs.items()), [((ns_uri, "attr"), "val")]) + self.assertEquals(list(attrs.values()), ["val"]) + self.assertEquals(attrs.getValue((ns_uri, "attr")), "val") + self.assertEquals(attrs[(ns_uri, "attr")], "val") -xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read() + # ===== InputSource support + + def test_expat_inpsource_filename(self): + parser = create_parser() + result = StringIO() + xmlgen = XMLGenerator(result) + + parser.setContentHandler(xmlgen) + parser.parse(findfile("test"+os.extsep+"xml")) + + self.assertEquals(result.getvalue(), xml_test_out) + + def test_expat_inpsource_sysid(self): + parser = create_parser() + result = StringIO() + xmlgen = XMLGenerator(result) + + parser.setContentHandler(xmlgen) + parser.parse(InputSource(findfile("test"+os.extsep+"xml"))) + + self.assertEquals(result.getvalue(), xml_test_out) + + def test_expat_inpsource_stream(self): + parser = create_parser() + result = StringIO() + xmlgen = XMLGenerator(result) + + parser.setContentHandler(xmlgen) + inpsrc = InputSource() + inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml"))) + parser.parse(inpsrc) + + self.assertEquals(result.getvalue(), xml_test_out) + + # ===== IncrementalParser support -def test_expat_inpsource_filename(): - parser = create_parser() - result = StringIO() - xmlgen = XMLGenerator(result) - - parser.setContentHandler(xmlgen) - parser.parse(findfile("test"+os.extsep+"xml")) - - return result.getvalue() == xml_test_out - -def test_expat_inpsource_sysid(): - parser = create_parser() - result = StringIO() - xmlgen = XMLGenerator(result) - - parser.setContentHandler(xmlgen) - parser.parse(InputSource(findfile("test"+os.extsep+"xml"))) - - return result.getvalue() == xml_test_out - -def test_expat_inpsource_stream(): - parser = create_parser() - result = StringIO() - xmlgen = XMLGenerator(result) - - parser.setContentHandler(xmlgen) - inpsrc = InputSource() - inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml"))) - parser.parse(inpsrc) - - return result.getvalue() == xml_test_out - -# ===== IncrementalParser support - -def test_expat_incremental(): - result = StringIO() - xmlgen = XMLGenerator(result) - parser = create_parser() - parser.setContentHandler(xmlgen) - - parser.feed("") - parser.feed("") - parser.close() - - return result.getvalue() == start + "" - -def test_expat_incremental_reset(): - result = StringIO() - xmlgen = XMLGenerator(result) - parser = create_parser() - parser.setContentHandler(xmlgen) - - parser.feed("") - parser.feed("text") - - result = StringIO() - xmlgen = XMLGenerator(result) - parser.setContentHandler(xmlgen) - parser.reset() - - parser.feed("") - parser.feed("text") - parser.feed("") - parser.close() - - return result.getvalue() == start + "text" - -# ===== Locator support - -def test_expat_locator_noinfo(): - result = StringIO() - xmlgen = XMLGenerator(result) - parser = create_parser() - parser.setContentHandler(xmlgen) - - parser.feed("") - parser.feed("") - parser.close() - - return parser.getSystemId() is None and \ - parser.getPublicId() is None and \ - parser.getLineNumber() == 1 - -def test_expat_locator_withinfo(): - result = StringIO() - xmlgen = XMLGenerator(result) - parser = create_parser() - parser.setContentHandler(xmlgen) - parser.parse(findfile("test.xml")) + def test_expat_incremental(self): + result = StringIO() + xmlgen = XMLGenerator(result) + parser = create_parser() + parser.setContentHandler(xmlgen) + + parser.feed("") + parser.feed("") + parser.close() + + self.assertEquals(result.getvalue(), start + "") + + def test_expat_incremental_reset(self): + result = StringIO() + xmlgen = XMLGenerator(result) + parser = create_parser() + parser.setContentHandler(xmlgen) + + parser.feed("") + parser.feed("text") + + result = StringIO() + xmlgen = XMLGenerator(result) + parser.setContentHandler(xmlgen) + parser.reset() + + parser.feed("") + parser.feed("text") + parser.feed("") + parser.close() + + self.assertEquals(result.getvalue(), start + "text") + + # ===== Locator support + + def test_expat_locator_noinfo(self): + result = StringIO() + xmlgen = XMLGenerator(result) + parser = create_parser() + parser.setContentHandler(xmlgen) + + parser.feed("") + parser.feed("") + parser.close() + + self.assertEquals(parser.getSystemId(), None) + self.assertEquals(parser.getPublicId(), None) + self.assertEquals(parser.getLineNumber(), 1) + + def test_expat_locator_withinfo(self): + result = StringIO() + xmlgen = XMLGenerator(result) + parser = create_parser() + parser.setContentHandler(xmlgen) + parser.parse(findfile("test.xml")) - return parser.getSystemId() == findfile("test.xml") and \ - parser.getPublicId() is None + self.assertEquals(parser.getSystemId(), findfile("test.xml")) + self.assertEquals(parser.getPublicId(), None) # =========================================================================== @@ -507,63 +546,59 @@ # # =========================================================================== -def test_expat_inpsource_location(): - parser = create_parser() - parser.setContentHandler(ContentHandler()) # do nothing - source = InputSource() - source.setByteStream(StringIO("")) #ill-formed - name = "a file name" - source.setSystemId(name) - try: - parser.parse(source) - except SAXException as e: - return e.getSystemId() == name - -def test_expat_incomplete(): - parser = create_parser() - parser.setContentHandler(ContentHandler()) # do nothing - try: - parser.parse(StringIO("")) - except SAXParseException: - return 1 # ok, error found - else: - return 0 - -def test_sax_parse_exception_str(): - # pass various values from a locator to the SAXParseException to - # make sure that the __str__() doesn't fall apart when None is - # passed instead of an integer line and column number - # - # use "normal" values for the locator: - str(SAXParseException("message", None, - DummyLocator(1, 1))) - # use None for the line number: - str(SAXParseException("message", None, - DummyLocator(None, 1))) - # use None for the column number: - str(SAXParseException("message", None, - DummyLocator(1, None))) - # use None for both: - str(SAXParseException("message", None, - DummyLocator(None, None))) - return 1 - -class DummyLocator: - def __init__(self, lineno, colno): - self._lineno = lineno - self._colno = colno - - def getPublicId(self): - return "pubid" +class ErrorReportingTest(unittest.TestCase): + def test_expat_inpsource_location(self): + parser = create_parser() + parser.setContentHandler(ContentHandler()) # do nothing + source = InputSource() + source.setByteStream(StringIO("")) #ill-formed + name = "a file name" + source.setSystemId(name) + try: + parser.parse(source) + self.fail() + except SAXException as e: + self.assertEquals(e.getSystemId(), name) + + def test_expat_incomplete(self): + parser = create_parser() + parser.setContentHandler(ContentHandler()) # do nothing + self.assertRaises(SAXParseException, parser.parse, StringIO("")) + + def test_sax_parse_exception_str(self): + # pass various values from a locator to the SAXParseException to + # make sure that the __str__() doesn't fall apart when None is + # passed instead of an integer line and column number + # + # use "normal" values for the locator: + str(SAXParseException("message", None, + self.DummyLocator(1, 1))) + # use None for the line number: + str(SAXParseException("message", None, + self.DummyLocator(None, 1))) + # use None for the column number: + str(SAXParseException("message", None, + self.DummyLocator(1, None))) + # use None for both: + str(SAXParseException("message", None, + self.DummyLocator(None, None))) + + class DummyLocator: + def __init__(self, lineno, colno): + self._lineno = lineno + self._colno = colno + + def getPublicId(self): + return "pubid" - def getSystemId(self): - return "sysid" + def getSystemId(self): + return "sysid" - def getLineNumber(self): - return self._lineno + def getLineNumber(self): + return self._lineno - def getColumnNumber(self): - return self._colno + def getColumnNumber(self): + return self._colno # =========================================================================== # @@ -571,217 +606,91 @@ # # =========================================================================== -# ===== AttributesImpl +class XmlReaderTest(XmlTestBase): -def verify_empty_attrs(attrs): - try: - attrs.getValue("attr") - gvk = 0 - except KeyError: - gvk = 1 - - try: - attrs.getValueByQName("attr") - gvqk = 0 - except KeyError: - gvqk = 1 - - try: - attrs.getNameByQName("attr") - gnqk = 0 - except KeyError: - gnqk = 1 - - try: - attrs.getQNameByName("attr") - gqnk = 0 - except KeyError: - gqnk = 1 - - try: - attrs["attr"] - gik = 0 - except KeyError: - gik = 1 - - return attrs.getLength() == 0 and \ - attrs.getNames() == [] and \ - attrs.getQNames() == [] and \ - len(attrs) == 0 and \ - "attr" not in attrs and \ - attrs.keys() == [] and \ - attrs.get("attrs") is None and \ - attrs.get("attrs", 25) == 25 and \ - attrs.items() == [] and \ - attrs.values() == [] and \ - gvk and gvqk and gnqk and gik and gqnk - -def verify_attrs_wattr(attrs): - return attrs.getLength() == 1 and \ - attrs.getNames() == ["attr"] and \ - attrs.getQNames() == ["attr"] and \ - len(attrs) == 1 and \ - "attr" in attrs and \ - attrs.keys() == ["attr"] and \ - attrs.get("attr") == "val" and \ - attrs.get("attr", 25) == "val" and \ - attrs.items() == [("attr", "val")] and \ - attrs.values() == ["val"] and \ - attrs.getValue("attr") == "val" and \ - attrs.getValueByQName("attr") == "val" and \ - attrs.getNameByQName("attr") == "attr" and \ - attrs["attr"] == "val" and \ - attrs.getQNameByName("attr") == "attr" - -def test_attrs_empty(): - return verify_empty_attrs(AttributesImpl({})) - -def test_attrs_wattr(): - return verify_attrs_wattr(AttributesImpl({"attr" : "val"})) - -# ===== AttributesImpl - -def verify_empty_nsattrs(attrs): - try: - attrs.getValue((ns_uri, "attr")) - gvk = 0 - except KeyError: - gvk = 1 - - try: - attrs.getValueByQName("ns:attr") - gvqk = 0 - except KeyError: - gvqk = 1 - - try: - attrs.getNameByQName("ns:attr") - gnqk = 0 - except KeyError: - gnqk = 1 - - try: - attrs.getQNameByName((ns_uri, "attr")) - gqnk = 0 - except KeyError: - gqnk = 1 - - try: - attrs[(ns_uri, "attr")] - gik = 0 - except KeyError: - gik = 1 - - return attrs.getLength() == 0 and \ - attrs.getNames() == [] and \ - attrs.getQNames() == [] and \ - len(attrs) == 0 and \ - (ns_uri, "attr") not in attrs and \ - attrs.keys() == [] and \ - attrs.get((ns_uri, "attr")) is None and \ - attrs.get((ns_uri, "attr"), 25) == 25 and \ - attrs.items() == [] and \ - attrs.values() == [] and \ - gvk and gvqk and gnqk and gik and gqnk - -def test_nsattrs_empty(): - return verify_empty_nsattrs(AttributesNSImpl({}, {})) - -def test_nsattrs_wattr(): - attrs = AttributesNSImpl({(ns_uri, "attr") : "val"}, - {(ns_uri, "attr") : "ns:attr"}) - - return attrs.getLength() == 1 and \ - attrs.getNames() == [(ns_uri, "attr")] and \ - attrs.getQNames() == ["ns:attr"] and \ - len(attrs) == 1 and \ - (ns_uri, "attr") in attrs and \ - attrs.keys() == [(ns_uri, "attr")] and \ - attrs.get((ns_uri, "attr")) == "val" and \ - attrs.get((ns_uri, "attr"), 25) == "val" and \ - attrs.items() == [((ns_uri, "attr"), "val")] and \ - attrs.values() == ["val"] and \ - attrs.getValue((ns_uri, "attr")) == "val" and \ - attrs.getValueByQName("ns:attr") == "val" and \ - attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \ - attrs[(ns_uri, "attr")] == "val" and \ - attrs.getQNameByName((ns_uri, "attr")) == "ns:attr" - - -# During the development of Python 2.5, an attempt to move the "xml" -# package implementation to a new package ("xmlcore") proved painful. -# The goal of this change was to allow applications to be able to -# obtain and rely on behavior in the standard library implementation -# of the XML support without needing to be concerned about the -# availability of the PyXML implementation. -# -# While the existing import hackery in Lib/xml/__init__.py can cause -# PyXML's _xmlpus package to supplant the "xml" package, that only -# works because either implementation uses the "xml" package name for -# imports. -# -# The move resulted in a number of problems related to the fact that -# the import machinery's "package context" is based on the name that's -# being imported rather than the __name__ of the actual package -# containment; it wasn't possible for the "xml" package to be replaced -# by a simple module that indirected imports to the "xmlcore" package. -# -# The following two tests exercised bugs that were introduced in that -# attempt. Keeping these tests around will help detect problems with -# other attempts to provide reliable access to the standard library's -# implementation of the XML support. - -def test_sf_1511497(): - # Bug report: http://www.python.org/sf/1511497 - import sys - old_modules = sys.modules.copy() - for modname in list(sys.modules.keys()): - if modname.startswith("xml."): - del sys.modules[modname] - try: - import xml.sax.expatreader - module = xml.sax.expatreader - return module.__name__ == "xml.sax.expatreader" - finally: - sys.modules.update(old_modules) - -def test_sf_1513611(): - # Bug report: http://www.python.org/sf/1513611 - sio = StringIO("invalid") - parser = make_parser() - from xml.sax import SAXParseException - try: - parser.parse(sio) - except SAXParseException: - return True - else: - return False - -# ===== Main program - -def make_test_output(): - parser = create_parser() - result = StringIO() - xmlgen = XMLGenerator(result) - - parser.setContentHandler(xmlgen) - parser.parse(findfile("test"+os.extsep+"xml")) - - outf = open(findfile("test"+os.extsep+"xml"+os.extsep+"out"), "w") - outf.write(result.getvalue()) - outf.close() - -items = sorted(locals().items()) -for (name, value) in items: - if name[ : 5] == "test_": - confirm(value(), name) -# We delete the items variable so that the assignment to items above -# doesn't pick up the old value of items (which messes with attempts -# to find reference leaks). -del items - -if verbose: - print("%d tests, %d failures" % (tests, len(failures))) -if failures: - raise TestFailed("%d of %d tests failed: %s" - % (len(failures), tests, ", ".join(failures))) + # ===== AttributesImpl + def test_attrs_empty(self): + self.verify_empty_attrs(AttributesImpl({})) + + def test_attrs_wattr(self): + self.verify_attrs_wattr(AttributesImpl({"attr" : "val"})) + + def test_nsattrs_empty(self): + self.verify_empty_nsattrs(AttributesNSImpl({}, {})) + + def test_nsattrs_wattr(self): + attrs = AttributesNSImpl({(ns_uri, "attr") : "val"}, + {(ns_uri, "attr") : "ns:attr"}) + + self.assertEquals(attrs.getLength(), 1) + self.assertEquals(attrs.getNames(), [(ns_uri, "attr")]) + self.assertEquals(attrs.getQNames(), ["ns:attr"]) + self.assertEquals(len(attrs), 1) + self.assertTrue((ns_uri, "attr") in attrs) + self.assertEquals(list(attrs.keys()), [(ns_uri, "attr")]) + self.assertEquals(attrs.get((ns_uri, "attr")), "val") + self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val") + self.assertEquals(list(attrs.items()), [((ns_uri, "attr"), "val")]) + self.assertEquals(list(attrs.values()), ["val"]) + self.assertEquals(attrs.getValue((ns_uri, "attr")), "val") + self.assertEquals(attrs.getValueByQName("ns:attr"), "val") + self.assertEquals(attrs.getNameByQName("ns:attr"), (ns_uri, "attr")) + self.assertEquals(attrs[(ns_uri, "attr")], "val") + self.assertEquals(attrs.getQNameByName((ns_uri, "attr")), "ns:attr") + + + # During the development of Python 2.5, an attempt to move the "xml" + # package implementation to a new package ("xmlcore") proved painful. + # The goal of this change was to allow applications to be able to + # obtain and rely on behavior in the standard library implementation + # of the XML support without needing to be concerned about the + # availability of the PyXML implementation. + # + # While the existing import hackery in Lib/xml/__init__.py can cause + # PyXML's _xmlpus package to supplant the "xml" package, that only + # works because either implementation uses the "xml" package name for + # imports. + # + # The move resulted in a number of problems related to the fact that + # the import machinery's "package context" is based on the name that's + # being imported rather than the __name__ of the actual package + # containment; it wasn't possible for the "xml" package to be replaced + # by a simple module that indirected imports to the "xmlcore" package. + # + # The following two tests exercised bugs that were introduced in that + # attempt. Keeping these tests around will help detect problems with + # other attempts to provide reliable access to the standard library's + # implementation of the XML support. + + def test_sf_1511497(self): + # Bug report: http://www.python.org/sf/1511497 + import sys + old_modules = sys.modules.copy() + for modname in list(sys.modules.keys()): + if modname.startswith("xml."): + del sys.modules[modname] + try: + import xml.sax.expatreader + module = xml.sax.expatreader + self.assertEquals(module.__name__, "xml.sax.expatreader") + finally: + sys.modules.update(old_modules) + + def test_sf_1513611(self): + # Bug report: http://www.python.org/sf/1513611 + sio = StringIO("invalid") + parser = make_parser() + from xml.sax import SAXParseException + self.assertRaises(SAXParseException, parser.parse, sio) + + +def unittest_main(): + run_unittest(MakeParserTest, + SaxutilsTest, + XmlgenTest, + ExpatReaderTest, + ErrorReportingTest, + XmlReaderTest) + +if __name__ == "__main__": + unittest_main() Modified: python/branches/p3yk/Lib/test/test_scope.py ============================================================================== --- python/branches/p3yk/Lib/test/test_scope.py (original) +++ python/branches/p3yk/Lib/test/test_scope.py Fri Apr 27 21:54:29 2007 @@ -477,6 +477,39 @@ del d['h'] self.assertEqual(d, {'x': 2, 'y': 7, 'w': 6}) + def testLocalsClass(self): + # This test verifies that calling locals() does not pollute + # the local namespace of the class with free variables. Old + # versions of Python had a bug, where a free variable being + # passed through a class namespace would be inserted into + # locals() by locals() or exec or a trace function. + # + # The real bug lies in frame code that copies variables + # between fast locals and the locals dict, e.g. when executing + # a trace function. + + def f(x): + class C: + x = 12 + def m(self): + return x + locals() + return C + + self.assertEqual(f(1).x, 12) + + def f(x): + class C: + y = x + def m(self): + return x + z = list(locals()) + return C + + varnames = f(1).z + self.assert_("x" not in varnames) + self.assert_("y" in varnames) + def testBoundAndFree(self): # var is bound and free in class @@ -607,7 +640,7 @@ c = f(0) self.assertEqual(c.get(), 1) self.assert_("x" not in c.__class__.__dict__) - + def testNonLocalGenerator(self): Modified: python/branches/p3yk/Lib/test/test_set.py ============================================================================== --- python/branches/p3yk/Lib/test/test_set.py (original) +++ python/branches/p3yk/Lib/test/test_set.py Fri Apr 27 21:54:29 2007 @@ -288,10 +288,17 @@ s = self.thetype(d) self.assertEqual(sum(elem.hash_count for elem in d), n) s.difference(d) - self.assertEqual(sum(elem.hash_count for elem in d), n) + self.assertEqual(sum(elem.hash_count for elem in d), n) if hasattr(s, 'symmetric_difference_update'): s.symmetric_difference_update(d) - self.assertEqual(sum(elem.hash_count for elem in d), n) + self.assertEqual(sum(elem.hash_count for elem in d), n) + d2 = dict.fromkeys(set(d)) + self.assertEqual(sum(elem.hash_count for elem in d), n) + d3 = dict.fromkeys(frozenset(d)) + self.assertEqual(sum(elem.hash_count for elem in d), n) + d3 = dict.fromkeys(frozenset(d), 123) + self.assertEqual(sum(elem.hash_count for elem in d), n) + self.assertEqual(d3, dict.fromkeys(d, 123)) class TestSet(TestJointOps): thetype = set Modified: python/branches/p3yk/Lib/test/test_slice.py ============================================================================== --- python/branches/p3yk/Lib/test/test_slice.py (original) +++ python/branches/p3yk/Lib/test/test_slice.py Fri Apr 27 21:54:29 2007 @@ -2,6 +2,7 @@ import unittest from test import test_support +from cPickle import loads, dumps import sys @@ -92,6 +93,24 @@ self.assertRaises(OverflowError, slice(None).indices, 1<<100) + def test_setslice_without_getslice(self): + tmp = [] + class X(object): + def __setslice__(self, i, j, k): + tmp.append((i, j, k)) + + x = X() + x[1:2] = 42 + self.assertEquals(tmp, [(1, 2, 42)]) + + def test_pickle(self): + s = slice(10, 20, 3) + for protocol in (0,1,2): + t = loads(dumps(s, protocol)) + self.assertEqual(s, t) + self.assertEqual(s.indices(15), t.indices(15)) + self.assertNotEqual(id(s), id(t)) + def test_main(): test_support.run_unittest(SliceTest) Modified: python/branches/p3yk/Lib/test/test_socket.py ============================================================================== --- python/branches/p3yk/Lib/test/test_socket.py (original) +++ python/branches/p3yk/Lib/test/test_socket.py Fri Apr 27 21:54:29 2007 @@ -75,7 +75,7 @@ Note, the server setup function cannot call any blocking functions that rely on the client thread during setup, - unless serverExplicityReady() is called just before + unless serverExplicitReady() is called just before the blocking call (such as in setting up a client/server connection and performing the accept() in setUp(). """ @@ -597,6 +597,13 @@ def _testRecvFrom(self): self.cli.sendto(MSG, 0, (HOST, PORT)) + def testRecvFromNegative(self): + # Negative lengths passed to recvfrom should give ValueError. + self.assertRaises(ValueError, self.serv.recvfrom, -1) + + def _testRecvFromNegative(self): + self.cli.sendto(MSG, 0, (HOST, PORT)) + class TCPCloserTest(ThreadedTCPSocketTest): def testClose(self): @@ -810,6 +817,98 @@ bufsize = 2 # Exercise the buffering code +class NetworkConnectionTest(object): + """Prove network connection.""" + def clientSetUp(self): + self.cli = socket.create_connection((HOST, PORT)) + self.serv_conn = self.cli + +class BasicTCPTest2(NetworkConnectionTest, BasicTCPTest): + """Tests that NetworkConnection does not break existing TCP functionality. + """ + +class NetworkConnectionNoServer(unittest.TestCase): + def testWithoutServer(self): + self.failUnlessRaises(socket.error, lambda: socket.create_connection((HOST, PORT))) + +class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest): + + def __init__(self, methodName='runTest'): + SocketTCPTest.__init__(self, methodName=methodName) + ThreadableTest.__init__(self) + + def clientSetUp(self): + pass + + def clientTearDown(self): + self.cli.close() + self.cli = None + ThreadableTest.clientTearDown(self) + + def _justAccept(self): + conn, addr = self.serv.accept() + + testFamily = _justAccept + def _testFamily(self): + self.cli = socket.create_connection((HOST, PORT), timeout=30) + self.assertEqual(self.cli.family, 2) + + testTimeoutDefault = _justAccept + def _testTimeoutDefault(self): + self.cli = socket.create_connection((HOST, PORT)) + self.assertTrue(self.cli.gettimeout() is None) + + testTimeoutValueNamed = _justAccept + def _testTimeoutValueNamed(self): + self.cli = socket.create_connection((HOST, PORT), timeout=30) + self.assertEqual(self.cli.gettimeout(), 30) + + testTimeoutValueNonamed = _justAccept + def _testTimeoutValueNonamed(self): + self.cli = socket.create_connection((HOST, PORT), 30) + self.assertEqual(self.cli.gettimeout(), 30) + + testTimeoutNone = _justAccept + def _testTimeoutNone(self): + previous = socket.getdefaulttimeout() + socket.setdefaulttimeout(30) + try: + self.cli = socket.create_connection((HOST, PORT), timeout=None) + finally: + socket.setdefaulttimeout(previous) + self.assertEqual(self.cli.gettimeout(), 30) + + +class NetworkConnectionBehaviourTest(SocketTCPTest, ThreadableTest): + + def __init__(self, methodName='runTest'): + SocketTCPTest.__init__(self, methodName=methodName) + ThreadableTest.__init__(self) + + def clientSetUp(self): + pass + + def clientTearDown(self): + self.cli.close() + self.cli = None + ThreadableTest.clientTearDown(self) + + def testInsideTimeout(self): + conn, addr = self.serv.accept() + time.sleep(3) + conn.send("done!") + testOutsideTimeout = testInsideTimeout + + def _testInsideTimeout(self): + self.cli = sock = socket.create_connection((HOST, PORT)) + data = sock.recv(5) + self.assertEqual(data, "done!") + + def _testOutsideTimeout(self): + self.cli = sock = socket.create_connection((HOST, PORT), timeout=1) + self.failUnlessRaises(socket.timeout, lambda: sock.recv(5)) + + class Urllib2FileobjectTest(unittest.TestCase): # urllib2.HTTPHandler has "borrowed" socket._fileobject, and requires that @@ -977,7 +1076,7 @@ def test_main(): tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, - TestExceptions, BufferIOTest] + TestExceptions, BufferIOTest, BasicTCPTest2] if sys.platform != 'mac': tests.extend([ BasicUDPTest, UDPTimeoutTest ]) @@ -988,6 +1087,9 @@ LineBufferedFileObjectClassTestCase, SmallBufferedFileObjectClassTestCase, Urllib2FileobjectTest, + NetworkConnectionNoServer, + NetworkConnectionAttributesTest, + NetworkConnectionBehaviourTest, ]) if hasattr(socket, "socketpair"): tests.append(BasicSocketPairTest) Modified: python/branches/p3yk/Lib/test/test_socket_ssl.py ============================================================================== --- python/branches/p3yk/Lib/test/test_socket_ssl.py (original) +++ python/branches/p3yk/Lib/test/test_socket_ssl.py Fri Apr 27 21:54:29 2007 @@ -1,128 +1,221 @@ # Test just the SSL support in the socket module, in a moderately bogus way. import sys +import unittest from test import test_support import socket import errno +import threading +import subprocess +import time +import os +import urllib -# Optionally test SSL support. This requires the 'network' resource as given -# on the regrtest command line. -skip_expected = not (test_support.is_resource_enabled('network') and - hasattr(socket, "ssl")) +# Optionally test SSL support, if we have it in the tested platform +skip_expected = not hasattr(socket, "ssl") -def test_basic(): - test_support.requires('network') +class ConnectedTests(unittest.TestCase): - import urllib - - if test_support.verbose: - print("test_basic ...") - - socket.RAND_status() - try: - socket.RAND_egd(1) - except TypeError: - pass - else: - print("didn't raise TypeError") - socket.RAND_add("this is a random string", 75.0) + def testBasic(self): + socket.RAND_status() + try: + socket.RAND_egd(1) + except TypeError: + pass + else: + print("didn't raise TypeError") + socket.RAND_add("this is a random string", 75.0) - f = urllib.urlopen('https://sf.net') - buf = f.read() - f.close() - -def test_timeout(): - test_support.requires('network') - - def error_msg(extra_msg): - print("""\ - WARNING: an attempt to connect to %r %s, in - test_timeout. That may be legitimate, but is not the outcome we hoped - for. If this message is seen often, test_timeout should be changed to - use a more reliable address.""" % (ADDR, extra_msg), file=sys.stderr) - - if test_support.verbose: - print("test_timeout ...") - - # A service which issues a welcome banner (without need to write - # anything). - # XXX ("gmail.org", 995) has been unreliable so far, from time to time - # XXX non-responsive for hours on end (& across all buildbot slaves, - # XXX so that's not just a local thing). - ADDR = "gmail.org", 995 + with test_support.transient_internet(): + f = urllib.urlopen('https://sf.net') + buf = f.read() + f.close() + + def testTimeout(self): + def error_msg(extra_msg): + print("""\ + WARNING: an attempt to connect to %r %s, in + test_timeout. That may be legitimate, but is not the outcome we + hoped for. If this message is seen often, test_timeout should be + changed to use a more reliable address.""" % (ADDR, extra_msg), file=sys.stderr) + + # A service which issues a welcome banner (without need to write + # anything). + # XXX ("gmail.org", 995) has been unreliable so far, from time to + # XXX time non-responsive for hours on end (& across all buildbot + # XXX slaves, so that's not just a local thing). + ADDR = "gmail.org", 995 - s = socket.socket() - s.settimeout(30.0) - try: - s.connect(ADDR) - except socket.timeout: - error_msg('timed out') - return - except socket.error as exc: # In case connection is refused. - if exc.args[0] == errno.ECONNREFUSED: - error_msg('was refused') + s = socket.socket() + s.settimeout(30.0) + try: + s.connect(ADDR) + except socket.timeout: + error_msg('timed out') return - else: - raise + except socket.error as exc: # In case connection is refused. + if exc.args[0] == errno.ECONNREFUSED: + error_msg('was refused') + return + else: + raise + + ss = socket.ssl(s) + # Read part of return welcome banner twice. + ss.read(1) + ss.read(1) + s.close() + +class BasicTests(unittest.TestCase): + + def testRudeShutdown(self): + # Some random port to connect to. + PORT = [9934] + + listener_ready = threading.Event() + listener_gone = threading.Event() + + # `listener` runs in a thread. It opens a socket listening on + # PORT, and sits in an accept() until the main thread connects. + # Then it rudely closes the socket, and sets Event `listener_gone` + # to let the main thread know the socket is gone. + def listener(): + s = socket.socket() + PORT[0] = test_support.bind_port(s, '', PORT[0]) + s.listen(5) + listener_ready.set() + s.accept() + s = None # reclaim the socket object, which also closes it + listener_gone.set() + + def connector(): + listener_ready.wait() + s = socket.socket() + s.connect(('localhost', PORT[0])) + listener_gone.wait() + try: + ssl_sock = socket.ssl(s) + except socket.sslerror: + pass + else: + raise test_support.TestFailed( + 'connecting to closed SSL socket should have failed') - ss = socket.ssl(s) - # Read part of return welcome banner twice. - ss.read(1) - ss.read(1) - s.close() - -def test_rude_shutdown(): - if test_support.verbose: - print("test_rude_shutdown ...") + t = threading.Thread(target=listener) + t.start() + connector() + t.join() - try: - import threading - except ImportError: - return - - # Some random port to connect to. - PORT = [9934] - - listener_ready = threading.Event() - listener_gone = threading.Event() - - # `listener` runs in a thread. It opens a socket listening on PORT, and - # sits in an accept() until the main thread connects. Then it rudely - # closes the socket, and sets Event `listener_gone` to let the main thread - # know the socket is gone. - def listener(): +class OpenSSLTests(unittest.TestCase): + + def testBasic(self): s = socket.socket() - PORT[0] = test_support.bind_port(s, '', PORT[0]) - s.listen(5) - listener_ready.set() - s.accept() - s = None # reclaim the socket object, which also closes it - listener_gone.set() + s.connect(("localhost", 4433)) + ss = socket.ssl(s) + ss.write("Foo\n") + i = ss.read(4) + self.assertEqual(i, "Foo\n") + s.close() + + def testMethods(self): + # read & write is already tried in the Basic test + # now we'll try to get the server info about certificates + # this came from the certificate I used, one I found in /usr/share/openssl + info = "/C=PT/ST=Queensland/L=Lisboa/O=Neuronio, Lda./OU=Desenvolvimento/CN=brutus.neuronio.pt/emailAddress=sampo at iki.fi" - def connector(): - listener_ready.wait() s = socket.socket() - s.connect(('localhost', PORT[0])) - listener_gone.wait() + s.connect(("localhost", 4433)) + ss = socket.ssl(s) + cert = ss.server() + self.assertEqual(cert, info) + cert = ss.issuer() + self.assertEqual(cert, info) + s.close() + + +class OpenSSLServer(threading.Thread): + def __init__(self): + self.s = None + self.keepServing = True + self._external() + if self.haveServer: + threading.Thread.__init__(self) + + def _external(self): + # let's find the .pem files + curdir = os.path.dirname(__file__) or os.curdir + cert_file = os.path.join(curdir, "ssl_cert.pem") + if not os.access(cert_file, os.F_OK): + raise ValueError("No cert file found! (tried %r)" % cert_file) + key_file = os.path.join(curdir, "ssl_key.pem") + if not os.access(key_file, os.F_OK): + raise ValueError("No key file found! (tried %r)" % key_file) + try: - ssl_sock = socket.ssl(s) - except socket.sslerror: - pass + cmd = "openssl s_server -cert %s -key %s -quiet" % (cert_file, key_file) + self.s = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + time.sleep(1) + except: + self.haveServer = False else: - raise test_support.TestFailed( - 'connecting to closed SSL socket should have failed') - - t = threading.Thread(target=listener) - t.start() - connector() - t.join() + # let's try if it is actually up + try: + s = socket.socket() + s.connect(("localhost", 4433)) + s.close() + if self.s.stdout.readline() != "ERROR\n": + raise ValueError + except: + self.haveServer = False + else: + self.haveServer = True + + def run(self): + while self.keepServing: + time.sleep(.5) + l = self.s.stdout.readline() + self.s.stdin.write(l) + + def shutdown(self): + self.keepServing = False + if not self.s: + return + if sys.platform == "win32": + subprocess.TerminateProcess(int(self.s._handle), -1) + else: + os.kill(self.s.pid, 15) def test_main(): if not hasattr(socket, "ssl"): raise test_support.TestSkipped("socket module has no ssl support") - test_rude_shutdown() - test_basic() - test_timeout() + + tests = [BasicTests] + + if test_support.is_resource_enabled('network'): + tests.append(ConnectedTests) + + # in these platforms we can kill the openssl process + if sys.platform in ("sunos5", "darwin", "linux1", + "linux2", "win32", "hp-ux11"): + + server = OpenSSLServer() + if server.haveServer: + tests.append(OpenSSLTests) + server.start() + else: + server = None + + thread_info = test_support.threading_setup() + + try: + test_support.run_unittest(*tests) + finally: + if server is not None and server.haveServer: + server.shutdown() + + test_support.threading_cleanup(*thread_info) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_socketserver.py ============================================================================== --- python/branches/p3yk/Lib/test/test_socketserver.py (original) +++ python/branches/p3yk/Lib/test/test_socketserver.py Fri Apr 27 21:54:29 2007 @@ -74,6 +74,7 @@ self.__addr = addr self.__svrcls = svrcls self.__hdlrcls = hdlrcls + self.ready = threading.Event() def run(self): class svrcls(MyMixinServer, self.__svrcls): pass @@ -81,9 +82,13 @@ svr = svrcls(self.__addr, self.__hdlrcls) # pull the address out of the server in case it changed # this can happen if another process is using the port - addr = getattr(svr, 'server_address') + addr = svr.server_address if addr: self.__addr = addr + if self.__addr != svr.socket.getsockname(): + raise RuntimeError('server_address was %s, expected %s' % + (self.__addr, svr.socket.getsockname())) + self.ready.set() if verbose: print("thread: serving three times") svr.serve_a_few() if verbose: print("thread: done") @@ -136,7 +141,9 @@ t.start() if verbose: print("server running") for i in range(NREQ): - time.sleep(DELAY) + t.ready.wait(10*DELAY) + if not t.ready.isSet(): + raise RuntimeError("Server not ready within a reasonable time") if verbose: print("test client", i) testfunc(proto, addr) if verbose: print("waiting for server") Modified: python/branches/p3yk/Lib/test/test_stringprep.py ============================================================================== --- python/branches/p3yk/Lib/test/test_stringprep.py (original) +++ python/branches/p3yk/Lib/test/test_stringprep.py Fri Apr 27 21:54:29 2007 @@ -1,88 +1,96 @@ # To fully test this module, we would need a copy of the stringprep tables. # Since we don't have them, this test checks only a few codepoints. -from test.test_support import verify, vereq +import unittest +from test import test_support -import stringprep from stringprep import * -verify(in_table_a1(u"\u0221")) -verify(not in_table_a1(u"\u0222")) +class StringprepTests(unittest.TestCase): + def test(self): + self.failUnless(in_table_a1(u"\u0221")) + self.failIf(in_table_a1(u"\u0222")) -verify(in_table_b1(u"\u00ad")) -verify(not in_table_b1(u"\u00ae")) + self.failUnless(in_table_b1(u"\u00ad")) + self.failIf(in_table_b1(u"\u00ae")) -verify(map_table_b2(u"\u0041"), u"\u0061") -verify(map_table_b2(u"\u0061"), u"\u0061") + self.failUnless(map_table_b2(u"\u0041"), u"\u0061") + self.failUnless(map_table_b2(u"\u0061"), u"\u0061") -verify(map_table_b3(u"\u0041"), u"\u0061") -verify(map_table_b3(u"\u0061"), u"\u0061") + self.failUnless(map_table_b3(u"\u0041"), u"\u0061") + self.failUnless(map_table_b3(u"\u0061"), u"\u0061") -verify(in_table_c11(u"\u0020")) -verify(not in_table_c11(u"\u0021")) + self.failUnless(in_table_c11(u"\u0020")) + self.failIf(in_table_c11(u"\u0021")) -verify(in_table_c12(u"\u00a0")) -verify(not in_table_c12(u"\u00a1")) + self.failUnless(in_table_c12(u"\u00a0")) + self.failIf(in_table_c12(u"\u00a1")) -verify(in_table_c12(u"\u00a0")) -verify(not in_table_c12(u"\u00a1")) + self.failUnless(in_table_c12(u"\u00a0")) + self.failIf(in_table_c12(u"\u00a1")) -verify(in_table_c11_c12(u"\u00a0")) -verify(not in_table_c11_c12(u"\u00a1")) + self.failUnless(in_table_c11_c12(u"\u00a0")) + self.failIf(in_table_c11_c12(u"\u00a1")) -verify(in_table_c21(u"\u001f")) -verify(not in_table_c21(u"\u0020")) + self.failUnless(in_table_c21(u"\u001f")) + self.failIf(in_table_c21(u"\u0020")) -verify(in_table_c22(u"\u009f")) -verify(not in_table_c22(u"\u00a0")) + self.failUnless(in_table_c22(u"\u009f")) + self.failIf(in_table_c22(u"\u00a0")) -verify(in_table_c21_c22(u"\u009f")) -verify(not in_table_c21_c22(u"\u00a0")) + self.failUnless(in_table_c21_c22(u"\u009f")) + self.failIf(in_table_c21_c22(u"\u00a0")) -verify(in_table_c3(u"\ue000")) -verify(not in_table_c3(u"\uf900")) + self.failUnless(in_table_c3(u"\ue000")) + self.failIf(in_table_c3(u"\uf900")) -verify(in_table_c4(u"\uffff")) -verify(not in_table_c4(u"\u0000")) + self.failUnless(in_table_c4(u"\uffff")) + self.failIf(in_table_c4(u"\u0000")) -verify(in_table_c5(u"\ud800")) -verify(not in_table_c5(u"\ud7ff")) + self.failUnless(in_table_c5(u"\ud800")) + self.failIf(in_table_c5(u"\ud7ff")) -verify(in_table_c6(u"\ufff9")) -verify(not in_table_c6(u"\ufffe")) + self.failUnless(in_table_c6(u"\ufff9")) + self.failIf(in_table_c6(u"\ufffe")) -verify(in_table_c7(u"\u2ff0")) -verify(not in_table_c7(u"\u2ffc")) + self.failUnless(in_table_c7(u"\u2ff0")) + self.failIf(in_table_c7(u"\u2ffc")) -verify(in_table_c8(u"\u0340")) -verify(not in_table_c8(u"\u0342")) + self.failUnless(in_table_c8(u"\u0340")) + self.failIf(in_table_c8(u"\u0342")) -# C.9 is not in the bmp -# verify(in_table_c9(u"\U000E0001")) -# verify(not in_table_c8(u"\U000E0002")) + # C.9 is not in the bmp + # self.failUnless(in_table_c9(u"\U000E0001")) + # self.failIf(in_table_c8(u"\U000E0002")) -verify(in_table_d1(u"\u05be")) -verify(not in_table_d1(u"\u05bf")) + self.failUnless(in_table_d1(u"\u05be")) + self.failIf(in_table_d1(u"\u05bf")) -verify(in_table_d2(u"\u0041")) -verify(not in_table_d2(u"\u0040")) + self.failUnless(in_table_d2(u"\u0041")) + self.failIf(in_table_d2(u"\u0040")) -# This would generate a hash of all predicates. However, running -# it is quite expensive, and only serves to detect changes in the -# unicode database. Instead, stringprep.py asserts the version of -# the database. + # This would generate a hash of all predicates. However, running + # it is quite expensive, and only serves to detect changes in the + # unicode database. Instead, stringprep.py asserts the version of + # the database. -# import hashlib -# predicates = [k for k in dir(stringprep) if k.startswith("in_table")] -# predicates.sort() -# for p in predicates: -# f = getattr(stringprep, p) -# # Collect all BMP code points -# data = ["0"] * 0x10000 -# for i in range(0x10000): -# if f(unichr(i)): -# data[i] = "1" -# data = "".join(data) -# h = hashlib.sha1() -# h.update(data) -# print p, h.hexdigest() + # import hashlib + # predicates = [k for k in dir(stringprep) if k.startswith("in_table")] + # predicates.sort() + # for p in predicates: + # f = getattr(stringprep, p) + # # Collect all BMP code points + # data = ["0"] * 0x10000 + # for i in range(0x10000): + # if f(unichr(i)): + # data[i] = "1" + # data = "".join(data) + # h = hashlib.sha1() + # h.update(data) + # print p, h.hexdigest() + +def test_main(): + test_support.run_unittest(StringprepTests) + +if __name__ == '__main__': + test_main() Modified: python/branches/p3yk/Lib/test/test_strptime.py ============================================================================== --- python/branches/p3yk/Lib/test/test_strptime.py (original) +++ python/branches/p3yk/Lib/test/test_strptime.py Fri Apr 27 21:54:29 2007 @@ -505,6 +505,35 @@ self.failIfEqual(locale_time_id, id(_strptime._TimeRE_cache.locale_time)) + def test_TimeRE_recreation(self): + # The TimeRE instance should be recreated upon changing the locale. + locale_info = locale.getlocale(locale.LC_TIME) + try: + locale.setlocale(locale.LC_TIME, ('en_US', 'UTF8')) + except locale.Error: + return + try: + _strptime.strptime('10', '%d') + # Get id of current cache object. + first_time_re_id = id(_strptime._TimeRE_cache) + try: + # Change the locale and force a recreation of the cache. + locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8')) + _strptime.strptime('10', '%d') + # Get the new cache object's id. + second_time_re_id = id(_strptime._TimeRE_cache) + # They should not be equal. + self.failIfEqual(first_time_re_id, second_time_re_id) + # Possible test locale is not supported while initial locale is. + # If this is the case just suppress the exception and fall-through + # to the reseting to the original locale. + except locale.Error: + pass + # Make sure we don't trample on the locale setting once we leave the + # test. + finally: + locale.setlocale(locale.LC_TIME, locale_info) + def test_main(): test_support.run_unittest( Modified: python/branches/p3yk/Lib/test/test_struct.py ============================================================================== --- python/branches/p3yk/Lib/test/test_struct.py (original) +++ python/branches/p3yk/Lib/test/test_struct.py Fri Apr 27 21:54:29 2007 @@ -614,53 +614,61 @@ assertRaises(struct.error, pack_into, small_buf, 0, test_string) assertRaises(struct.error, pack_into, small_buf, 2, test_string) +def test_unpack_with_buffer(): + # SF bug 1563759: struct.unpack doens't support buffer protocol objects + data1 = array.array('B', '\x12\x34\x56\x78') + data2 = buffer('......\x12\x34\x56\x78......', 6, 4) + for data in [data1, data2]: + value, = struct.unpack('>I', data) + vereq(value, 0x12345678) # Test methods to pack and unpack from buffers rather than strings. test_unpack_from() test_pack_into() test_pack_into_fn() +test_unpack_with_buffer() def test_bool(): for prefix in tuple("<>!=")+('',): false = (), [], [], '', 0 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2 - + falseFormat = prefix + 't' * len(false) if verbose: print('trying bool pack/unpack on', false, 'using format', falseFormat) packedFalse = struct.pack(falseFormat, *false) unpackedFalse = struct.unpack(falseFormat, packedFalse) - + trueFormat = prefix + 't' * len(true) if verbose: print('trying bool pack/unpack on', true, 'using format', trueFormat) packedTrue = struct.pack(trueFormat, *true) unpackedTrue = struct.unpack(trueFormat, packedTrue) - + if len(true) != len(unpackedTrue): raise TestFailed('unpacked true array is not of same size as input') if len(false) != len(unpackedFalse): raise TestFailed('unpacked false array is not of same size as input') - + for t in unpackedFalse: if t is not False: raise TestFailed('%r did not unpack as False' % t) for t in unpackedTrue: if t is not True: raise TestFailed('%r did not unpack as false' % t) - + if prefix and verbose: print('trying size of bool with format %r' % (prefix+'t')) packed = struct.pack(prefix+'t', 1) - + if len(packed) != struct.calcsize(prefix+'t'): raise TestFailed('packed length is not equal to calculated size') - + if len(packed) != 1 and prefix: raise TestFailed('encoded bool is not one byte: %r' % packed) elif not prefix and verbose: print('size of bool in native format is %i' % (len(packed))) - + for c in '\x01\x7f\xff\x0f\xf0': if struct.unpack('>t', c)[0] is not True: raise TestFailed('%c did not unpack as True' % c) Modified: python/branches/p3yk/Lib/test/test_structmembers.py ============================================================================== --- python/branches/p3yk/Lib/test/test_structmembers.py (original) +++ python/branches/p3yk/Lib/test/test_structmembers.py Fri Apr 27 21:54:29 2007 @@ -4,7 +4,7 @@ INT_MAX, INT_MIN, UINT_MAX, \ LONG_MAX, LONG_MIN, ULONG_MAX -import warnings, unittest, test.test_warnings +import warnings, unittest from test import test_support ts=test_structmembersType(1,2,3,4,5,6,7,8,9.99999,10.1010101010) @@ -39,34 +39,39 @@ ts.T_ULONG=ULONG_MAX self.assertEquals(ts.T_ULONG, ULONG_MAX) -class TestWarnings(test.test_warnings.TestModule): - def has_warned(self): - self.assertEqual(test.test_warnings.msg.category, - RuntimeWarning.__name__) +class TestWarnings(unittest.TestCase): + def has_warned(self, w): + self.assert_(w.category is RuntimeWarning) def test_byte_max(self): - ts.T_BYTE=CHAR_MAX+1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_BYTE=CHAR_MAX+1 + self.has_warned(w) def test_byte_min(self): - ts.T_BYTE=CHAR_MIN-1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_BYTE=CHAR_MIN-1 + self.has_warned(w) def test_ubyte_max(self): - ts.T_UBYTE=UCHAR_MAX+1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_UBYTE=UCHAR_MAX+1 + self.has_warned(w) def test_short_max(self): - ts.T_SHORT=SHRT_MAX+1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_SHORT=SHRT_MAX+1 + self.has_warned(w) def test_short_min(self): - ts.T_SHORT=SHRT_MIN-1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_SHORT=SHRT_MIN-1 + self.has_warned(w) def test_ushort_max(self): - ts.T_USHORT=USHRT_MAX+1 - self.has_warned() + with test_support.catch_warning() as w: + ts.T_USHORT=USHRT_MAX+1 + self.has_warned(w) Modified: python/branches/p3yk/Lib/test/test_support.py ============================================================================== --- python/branches/p3yk/Lib/test/test_support.py (original) +++ python/branches/p3yk/Lib/test/test_support.py Fri Apr 27 21:54:29 2007 @@ -1,11 +1,17 @@ """Supporting definitions for the Python regression tests.""" if __name__ != 'test.test_support': - raise ImportError, 'test_support must be imported from the test package' + raise ImportError('test_support must be imported from the test package') -from contextlib import contextmanager +import contextlib +import errno +import socket import sys +import os +import os.path import warnings +import types +import unittest class Error(Exception): """Base class for regression test exceptions.""" @@ -54,7 +60,6 @@ pass def unlink(filename): - import os try: os.unlink(filename) except OSError: @@ -64,7 +69,6 @@ '''"Forget" a module was ever imported by removing it from sys.modules and deleting any .pyc and .pyo files.''' unload(modname) - import os for dirname in sys.path: unlink(os.path.join(dirname, modname + os.extsep + 'pyc')) # Deleting the .pyo file cannot be within the 'try' for the .pyc since @@ -96,7 +100,6 @@ tests and we don't try multiple ports, the test can fails. This makes the test more robust.""" - import socket, errno # some random ports that hopefully no one is listening on. for port in [preferred_port, 9907, 10243, 32999]: try: @@ -107,7 +110,7 @@ if err != errno.EADDRINUSE: raise print(' WARNING: failed to listen on port %d, trying another' % port, file=sys.__stderr__) - raise TestFailed, 'unable to find port to listen on' + raise TestFailed('unable to find port to listen on') FUZZ = 1e-6 @@ -135,7 +138,6 @@ is_jython = sys.platform.startswith('java') -import os # Filename used for testing if os.name == 'java': # Jython disallows @ in module names @@ -197,13 +199,12 @@ if fp is not None: fp.close() unlink(TESTFN) -del os, fp +del fp def findfile(file, here=__file__): """Try to find a file on sys.path and the working directory. If it is not found the argument passed to the function is returned (this does not necessarily signal failure; could still be the legitimate path).""" - import os if os.path.isabs(file): return file path = sys.path @@ -235,7 +236,7 @@ """ if not (a == b): - raise TestFailed, "%r == %r" % (a, b) + raise TestFailed("%r == %r" % (a, b)) def sortdict(dict): "Like repr(dict), but in sorted order." @@ -254,7 +255,6 @@ def open_urlresource(url): import urllib, urlparse - import os.path filename = urlparse.urlparse(url)[2].split('/')[-1] # '/': it's URL! @@ -268,7 +268,7 @@ fn, _ = urllib.urlretrieve(url, filename) return open(fn) - at contextmanager + at contextlib.contextmanager def guard_warnings_filter(): """Guard the warnings filter from being permanently changed.""" original_filters = warnings.filters[:] @@ -277,14 +277,49 @@ finally: warnings.filters = original_filters +class WarningMessage(object): + "Holds the result of the latest showwarning() call" + def __init__(self): + self.message = None + self.category = None + self.filename = None + self.lineno = None + + def _showwarning(self, message, category, filename, lineno, file=None): + self.message = message + self.category = category + self.filename = filename + self.lineno = lineno + + at contextlib.contextmanager +def catch_warning(): + """ + Guard the warnings filter from being permanently changed and record the + data of the last warning that has been issued. + + Use like this: + + with catch_warning as w: + warnings.warn("foo") + assert str(w.message) == "foo" + """ + warning = WarningMessage() + original_filters = warnings.filters[:] + original_showwarning = warnings.showwarning + warnings.showwarning = warning._showwarning + try: + yield warning + finally: + warnings.showwarning = original_showwarning + warnings.filters = original_filters + class EnvironmentVarGuard(object): """Class to help protect the environment variable properly. Can be used as a context manager.""" def __init__(self): - from os import environ - self._environ = environ + self._environ = os.environ self._unset = set() self._reset = dict() @@ -309,6 +344,40 @@ for unset in self._unset: del self._environ[unset] +class TransientResource(object): + + """Raise ResourceDenied if an exception is raised while the context manager + is in effect that matches the specified exception and attributes.""" + + def __init__(self, exc, **kwargs): + self.exc = exc + self.attrs = kwargs + + def __enter__(self): + return self + + def __exit__(self, type_=None, value=None, traceback=None): + """If type_ is a subclass of self.exc and value has attributes matching + self.attrs, raise ResourceDenied. Otherwise let the exception + propagate (if any).""" + if type_ is not None and issubclass(self.exc, type_): + for attr, attr_value in self.attrs.items(): + if not hasattr(value, attr): + break + if getattr(value, attr) != attr_value: + break + else: + raise ResourceDenied("an optional resource is not available") + + +def transient_internet(): + """Return a context manager that raises ResourceDenied when various issues + with the Internet connection manifest themselves as exceptions.""" + time_out = TransientResource(IOError, errno=errno.ETIMEDOUT) + socket_peer_reset = TransientResource(socket.error, errno=errno.ECONNRESET) + ioerror_peer_reset = TransientResource(IOError, errno=errno.ECONNRESET) + return contextlib.nested(time_out, socket_peer_reset, ioerror_peer_reset) + #======================================================================= # Decorator for running a function in a different locale, correctly resetting @@ -432,10 +501,7 @@ return wrapper #======================================================================= -# Preliminary PyUNIT integration. - -import unittest - +# unittest integration. class BasicTestRunner: def run(self, test): @@ -444,7 +510,7 @@ return result -def run_suite(suite, testclass=None): +def _run_suite(suite): """Run tests from a unittest.TestSuite-derived class.""" if verbose: runner = unittest.TextTestRunner(sys.stdout, verbosity=2) @@ -458,28 +524,26 @@ elif len(result.failures) == 1 and not result.errors: err = result.failures[0][1] else: - if testclass is None: - msg = "errors occurred; run in verbose mode for details" - else: - msg = "errors occurred in %s.%s" \ - % (testclass.__module__, testclass.__name__) + msg = "errors occurred; run in verbose mode for details" raise TestFailed(msg) raise TestFailed(err) def run_unittest(*classes): """Run tests from unittest.TestCase-derived classes.""" + valid_types = (unittest.TestSuite, unittest.TestCase) suite = unittest.TestSuite() for cls in classes: - if isinstance(cls, (unittest.TestSuite, unittest.TestCase)): + if isinstance(cls, str): + if cls in sys.modules: + suite.addTest(unittest.findTestCases(sys.modules[cls])) + else: + raise ValueError("str arguments must be keys in sys.modules") + elif isinstance(cls, valid_types): suite.addTest(cls) else: suite.addTest(unittest.makeSuite(cls)) - if len(classes)==1: - testclass = classes[0] - else: - testclass = None - run_suite(suite, testclass) + _run_suite(suite) #======================================================================= @@ -545,7 +609,6 @@ # Reap all our dead child processes so we don't leave zombies around. # These hog resources and might be causing some of the buildbots to die. - import os if hasattr(os, 'waitpid'): any_process = -1 while True: Modified: python/branches/p3yk/Lib/test/test_syntax.py ============================================================================== --- python/branches/p3yk/Lib/test/test_syntax.py (original) +++ python/branches/p3yk/Lib/test/test_syntax.py Fri Apr 27 21:54:29 2007 @@ -374,7 +374,7 @@ Traceback (most recent call last): ... SyntaxError: name 'x' is parameter and nonlocal - + >>> def f(): ... global x ... nonlocal x @@ -403,7 +403,7 @@ ## Traceback (most recent call last): ## ... ## SyntaxWarning: name 'x' is assigned to before nonlocal declaration - + ## >>> def f(): ## ... x = 1 ## ... nonlocal x @@ -411,7 +411,56 @@ ## ... ## SyntaxWarning: name 'x' is assigned to before nonlocal declaration - + +This tests assignment-context; there was a bug in Python 2.5 where compiling +a complex 'if' (one with 'elif') would fail to notice an invalid suite, +leading to spurious errors. + + >>> if 1: + ... x() = 1 + ... elif 1: + ... pass + Traceback (most recent call last): + ... + SyntaxError: can't assign to function call (, line 2) + + >>> if 1: + ... pass + ... elif 1: + ... x() = 1 + Traceback (most recent call last): + ... + SyntaxError: can't assign to function call (, line 4) + + >>> if 1: + ... x() = 1 + ... elif 1: + ... pass + ... else: + ... pass + Traceback (most recent call last): + ... + SyntaxError: can't assign to function call (, line 2) + + >>> if 1: + ... pass + ... elif 1: + ... x() = 1 + ... else: + ... pass + Traceback (most recent call last): + ... + SyntaxError: can't assign to function call (, line 4) + + >>> if 1: + ... pass + ... elif 1: + ... pass + ... else: + ... x() = 1 + Traceback (most recent call last): + ... + SyntaxError: can't assign to function call (, line 6) """ Modified: python/branches/p3yk/Lib/test/test_tarfile.py ============================================================================== --- python/branches/p3yk/Lib/test/test_tarfile.py (original) +++ python/branches/p3yk/Lib/test/test_tarfile.py Fri Apr 27 21:54:29 2007 @@ -1,8 +1,12 @@ +# encoding: iso8859-1 + import sys import os import shutil import tempfile import StringIO +import md5 +import errno import unittest import tarfile @@ -20,452 +24,547 @@ except ImportError: bz2 = None +def md5sum(data): + return md5.new(data).hexdigest() + def path(path): return test_support.findfile(path) -testtar = path("testtar.tar") -tempdir = os.path.join(tempfile.gettempdir(), "testtar" + os.extsep + "dir") -tempname = test_support.TESTFN -membercount = 12 - -def tarname(comp=""): - if not comp: - return testtar - return os.path.join(tempdir, "%s%s%s" % (testtar, os.extsep, comp)) - -def dirname(): - if not os.path.exists(tempdir): - os.mkdir(tempdir) - return tempdir - -def tmpname(): - return tempname - - -class BaseTest(unittest.TestCase): - comp = '' - mode = 'r' - sep = ':' +TEMPDIR = os.path.join(tempfile.gettempdir(), "test_tarfile_tmp") +tarname = path("testtar.tar") +gzipname = os.path.join(TEMPDIR, "testtar.tar.gz") +bz2name = os.path.join(TEMPDIR, "testtar.tar.bz2") +tmpname = os.path.join(TEMPDIR, "tmp.tar") + +md5_regtype = "65f477c818ad9e15f7feab0c6d37742f" +md5_sparse = "a54fbc4ca4f4399a90e1b27164012fc6" + + +class ReadTest(unittest.TestCase): + + tarname = tarname + mode = "r:" def setUp(self): - mode = self.mode + self.sep + self.comp - self.tar = tarfile.open(tarname(self.comp), mode) + self.tar = tarfile.open(self.tarname, mode=self.mode, encoding="iso8859-1") def tearDown(self): self.tar.close() -class ReadTest(BaseTest): - def test(self): - """Test member extraction. - """ - members = 0 - for tarinfo in self.tar: - members += 1 - if not tarinfo.isreg(): - continue - f = self.tar.extractfile(tarinfo) - self.assert_(len(f.read()) == tarinfo.size, - "size read does not match expected size") - f.close() - - self.assert_(members == membercount, - "could not find all members") - - def test_sparse(self): - """Test sparse member extraction. - """ - if self.sep != "|": - f1 = self.tar.extractfile("S-SPARSE") - f2 = self.tar.extractfile("S-SPARSE-WITH-NULLS") - self.assert_(f1.read() == f2.read(), - "_FileObject failed on sparse file member") - - def test_readlines(self): - """Test readlines() method of _FileObject. - """ - if self.sep != "|": - filename = "0-REGTYPE-TEXT" - self.tar.extract(filename, dirname()) - f = open(os.path.join(dirname(), filename), "rU") - lines1 = f.readlines() - f.close() - lines2 = self.tar.extractfile(filename).readlines() - self.assert_(lines1 == lines2, - "_FileObject.readline() does not work correctly") - - def test_iter(self): - # Test iteration over ExFileObject. - if self.sep != "|": - filename = "0-REGTYPE-TEXT" - self.tar.extract(filename, dirname()) - f = open(os.path.join(dirname(), filename), "rU") - lines1 = f.readlines() - f.close() - lines2 = [line for line in self.tar.extractfile(filename)] - self.assert_(lines1 == lines2, - "ExFileObject iteration does not work correctly") - - def test_seek(self): - """Test seek() method of _FileObject, incl. random reading. - """ - if self.sep != "|": - filename = "0-REGTYPE-TEXT" - self.tar.extract(filename, dirname()) - f = open(os.path.join(dirname(), filename), "rb") - data = f.read() - f.close() - - tarinfo = self.tar.getmember(filename) - fobj = self.tar.extractfile(tarinfo) - - text = fobj.read() - fobj.seek(0) - self.assert_(0 == fobj.tell(), - "seek() to file's start failed") - fobj.seek(2048, 0) - self.assert_(2048 == fobj.tell(), - "seek() to absolute position failed") - fobj.seek(-1024, 1) - self.assert_(1024 == fobj.tell(), - "seek() to negative relative position failed") - fobj.seek(1024, 1) - self.assert_(2048 == fobj.tell(), - "seek() to positive relative position failed") - s = fobj.read(10) - self.assert_(s == data[2048:2058], - "read() after seek failed") - fobj.seek(0, 2) - self.assert_(tarinfo.size == fobj.tell(), - "seek() to file's end failed") - self.assert_(fobj.read() == "", - "read() at file's end did not return empty string") - fobj.seek(-tarinfo.size, 2) - self.assert_(0 == fobj.tell(), - "relative seek() to file's start failed") - fobj.seek(512) - s1 = fobj.readlines() - fobj.seek(512) - s2 = fobj.readlines() - self.assert_(s1 == s2, - "readlines() after seek failed") - fobj.seek(0) - self.assert_(len(fobj.readline()) == fobj.tell(), - "tell() after readline() failed") - fobj.seek(512) - self.assert_(len(fobj.readline()) + 512 == fobj.tell(), - "tell() after seek() and readline() failed") - fobj.seek(0) - line = fobj.readline() - self.assert_(fobj.read() == data[len(line):], - "read() after readline() failed") - fobj.close() +class UstarReadTest(ReadTest): - def test_old_dirtype(self): - """Test old style dirtype member (bug #1336623). - """ - # Old tars create directory members using a REGTYPE - # header with a "/" appended to the filename field. + def test_fileobj_regular_file(self): + tarinfo = self.tar.getmember("ustar/regtype") + fobj = self.tar.extractfile(tarinfo) + data = fobj.read() + self.assert_((len(data), md5sum(data)) == (tarinfo.size, md5_regtype), + "regular file extraction failed") + + def test_fileobj_readlines(self): + self.tar.extract("ustar/regtype", TEMPDIR) + tarinfo = self.tar.getmember("ustar/regtype") + fobj1 = open(os.path.join(TEMPDIR, "ustar/regtype"), "rU") + fobj2 = self.tar.extractfile(tarinfo) + + lines1 = fobj1.readlines() + lines2 = fobj2.readlines() + self.assert_(lines1 == lines2, + "fileobj.readlines() failed") + self.assert_(len(lines2) == 114, + "fileobj.readlines() failed") + self.assert_(lines2[83] == \ + "I will gladly admit that Python is not the fastest running scripting language.\n", + "fileobj.readlines() failed") + + def test_fileobj_iter(self): + self.tar.extract("ustar/regtype", TEMPDIR) + tarinfo = self.tar.getmember("ustar/regtype") + fobj1 = open(os.path.join(TEMPDIR, "ustar/regtype"), "rU") + fobj2 = self.tar.extractfile(tarinfo) + lines1 = fobj1.readlines() + lines2 = [line for line in fobj2] + self.assert_(lines1 == lines2, + "fileobj.__iter__() failed") + + def test_fileobj_seek(self): + self.tar.extract("ustar/regtype", TEMPDIR) + fobj = open(os.path.join(TEMPDIR, "ustar/regtype"), "rb") + data = fobj.read() + fobj.close() - # Create an old tar style directory entry. - filename = tmpname() - tarinfo = tarfile.TarInfo("directory/") - tarinfo.type = tarfile.REGTYPE + tarinfo = self.tar.getmember("ustar/regtype") + fobj = self.tar.extractfile(tarinfo) - fobj = open(filename, "w") - fobj.write(tarinfo.tobuf()) + text = fobj.read() + fobj.seek(0) + self.assert_(0 == fobj.tell(), + "seek() to file's start failed") + fobj.seek(2048, 0) + self.assert_(2048 == fobj.tell(), + "seek() to absolute position failed") + fobj.seek(-1024, 1) + self.assert_(1024 == fobj.tell(), + "seek() to negative relative position failed") + fobj.seek(1024, 1) + self.assert_(2048 == fobj.tell(), + "seek() to positive relative position failed") + s = fobj.read(10) + self.assert_(s == data[2048:2058], + "read() after seek failed") + fobj.seek(0, 2) + self.assert_(tarinfo.size == fobj.tell(), + "seek() to file's end failed") + self.assert_(fobj.read() == "", + "read() at file's end did not return empty string") + fobj.seek(-tarinfo.size, 2) + self.assert_(0 == fobj.tell(), + "relative seek() to file's start failed") + fobj.seek(512) + s1 = fobj.readlines() + fobj.seek(512) + s2 = fobj.readlines() + self.assert_(s1 == s2, + "readlines() after seek failed") + fobj.seek(0) + self.assert_(len(fobj.readline()) == fobj.tell(), + "tell() after readline() failed") + fobj.seek(512) + self.assert_(len(fobj.readline()) + 512 == fobj.tell(), + "tell() after seek() and readline() failed") + fobj.seek(0) + line = fobj.readline() + self.assert_(fobj.read() == data[len(line):], + "read() after readline() failed") fobj.close() - try: - # Test if it is still a directory entry when - # read back. - tar = tarfile.open(filename) - tarinfo = tar.getmembers()[0] - tar.close() - self.assert_(tarinfo.type == tarfile.DIRTYPE) - self.assert_(tarinfo.name.endswith("/")) - finally: - try: - os.unlink(filename) - except: - pass - -class ReadStreamTest(ReadTest): - sep = "|" - - def test(self): - """Test member extraction, and for StreamError when - seeking backwards. - """ - ReadTest.test(self) - tarinfo = self.tar.getmembers()[0] - f = self.tar.extractfile(tarinfo) - self.assertRaises(tarfile.StreamError, f.read) +class MiscReadTest(ReadTest): - def test_stream(self): - """Compare the normal tar and the stream tar. - """ - stream = self.tar - tar = tarfile.open(tarname(), 'r') - - while 1: - t1 = tar.next() - t2 = stream.next() - if t1 is None: - break - self.assert_(t2 is not None, "stream.next() failed.") + def test_no_filename(self): + fobj = open(self.tarname, "rb") + tar = tarfile.open(fileobj=fobj, mode=self.mode) + self.assertEqual(tar.name, os.path.abspath(fobj.name)) + + def test_fail_comp(self): + # For Gzip and Bz2 Tests: fail with a ReadError on an uncompressed file. + if self.mode == "r:": + return + self.assertRaises(tarfile.ReadError, tarfile.open, tarname, self.mode) + fobj = open(tarname, "rb") + self.assertRaises(tarfile.ReadError, tarfile.open, fileobj=fobj, mode=self.mode) + + def test_v7_dirtype(self): + # Test old style dirtype member (bug #1336623): + # Old V7 tars create directory members using an AREGTYPE + # header with a "/" appended to the filename field. + tarinfo = self.tar.getmember("misc/dirtype-old-v7") + self.assert_(tarinfo.type == tarfile.DIRTYPE, + "v7 dirtype failed") - if t2.islnk() or t2.issym(): - self.assertRaises(tarfile.StreamError, stream.extractfile, t2) - continue - v1 = tar.extractfile(t1) - v2 = stream.extractfile(t2) - if v1 is None: + def test_check_members(self): + for tarinfo in self.tar: + self.assert_(int(tarinfo.mtime) == 07606136617, + "wrong mtime for %s" % tarinfo.name) + if not tarinfo.name.startswith("ustar/"): continue - self.assert_(v2 is not None, "stream.extractfile() failed") - self.assert_(v1.read() == v2.read(), "stream extraction failed") + self.assert_(tarinfo.uname == "tarfile", + "wrong uname for %s" % tarinfo.name) - tar.close() - stream.close() + def test_find_members(self): + self.assert_(self.tar.getmembers()[-1].name == "misc/eof", + "could not find all members") + + def test_extract_hardlink(self): + # Test hardlink extraction (e.g. bug #857297). + tar = tarfile.open(tarname, errorlevel=1, encoding="iso8859-1") -class ReadDetectTest(ReadTest): + tar.extract("ustar/regtype", TEMPDIR) + try: + tar.extract("ustar/lnktype", TEMPDIR) + except EnvironmentError as e: + if e.errno == errno.ENOENT: + self.fail("hardlink not extracted properly") - def setUp(self): - self.tar = tarfile.open(tarname(self.comp), self.mode) + data = open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb").read() + self.assertEqual(md5sum(data), md5_regtype) -class ReadDetectFileobjTest(ReadTest): + try: + tar.extract("ustar/symtype", TEMPDIR) + except EnvironmentError as e: + if e.errno == errno.ENOENT: + self.fail("symlink not extracted properly") - def setUp(self): - name = tarname(self.comp) - self.tar = tarfile.open(name, mode=self.mode, - fileobj=open(name, "rb")) + data = open(os.path.join(TEMPDIR, "ustar/symtype"), "rb").read() + self.assertEqual(md5sum(data), md5_regtype) -class ReadAsteriskTest(ReadTest): - def setUp(self): - mode = self.mode + self.sep + "*" - self.tar = tarfile.open(tarname(self.comp), mode) +class StreamReadTest(ReadTest): -class ReadStreamAsteriskTest(ReadStreamTest): + mode="r|" - def setUp(self): - mode = self.mode + self.sep + "*" - self.tar = tarfile.open(tarname(self.comp), mode) + def test_fileobj_regular_file(self): + tarinfo = self.tar.next() # get "regtype" (can't use getmember) + fobj = self.tar.extractfile(tarinfo) + data = fobj.read() + self.assert_((len(data), md5sum(data)) == (tarinfo.size, md5_regtype), + "regular file extraction failed") -class WriteTest(BaseTest): - mode = 'w' + def test_provoke_stream_error(self): + tarinfos = self.tar.getmembers() + f = self.tar.extractfile(tarinfos[0]) # read the first member + self.assertRaises(tarfile.StreamError, f.read) - def setUp(self): - mode = self.mode + self.sep + self.comp - self.src = tarfile.open(tarname(self.comp), 'r') - self.dstname = tmpname() - self.dst = tarfile.open(self.dstname, mode) + def test_compare_members(self): + tar1 = tarfile.open(tarname, encoding="iso8859-1") + tar2 = self.tar + + while True: + t1 = tar1.next() + t2 = tar2.next() + if t1 is None: + break + self.assert_(t2 is not None, "stream.next() failed.") - def tearDown(self): - self.src.close() - self.dst.close() + if t2.islnk() or t2.issym(): + self.assertRaises(tarfile.StreamError, tar2.extractfile, t2) + continue - def test_posix(self): - self.dst.posix = 1 - self._test() + v1 = tar1.extractfile(t1) + v2 = tar2.extractfile(t2) + if v1 is None: + continue + self.assert_(v2 is not None, "stream.extractfile() failed") + self.assert_(v1.read() == v2.read(), "stream extraction failed") - def test_nonposix(self): - self.dst.posix = 0 - self._test() + tar1.close() - def test_small(self): - self.dst.add(os.path.join(os.path.dirname(__file__),"cfgparser.1")) - self.dst.close() - self.assertNotEqual(os.stat(self.dstname).st_size, 0) - - def _test(self): - for tarinfo in self.src: - if not tarinfo.isreg(): - continue - f = self.src.extractfile(tarinfo) - if self.dst.posix and len(tarinfo.name) > tarfile.LENGTH_NAME and "/" not in tarinfo.name: - self.assertRaises(ValueError, self.dst.addfile, - tarinfo, f) - else: - self.dst.addfile(tarinfo, f) - def test_add_self(self): - dstname = os.path.abspath(self.dstname) +class DetectReadTest(unittest.TestCase): - self.assertEqual(self.dst.name, dstname, "archive name must be absolute") + def _testfunc_file(self, name, mode): + try: + tarfile.open(name, mode) + except tarfile.ReadError: + self.fail() - self.dst.add(dstname) - self.assertEqual(self.dst.getnames(), [], "added the archive to itself") + def _testfunc_fileobj(self, name, mode): + try: + tarfile.open(name, mode, fileobj=open(name, "rb")) + except tarfile.ReadError: + self.fail() - cwd = os.getcwd() - os.chdir(dirname()) - self.dst.add(dstname) - os.chdir(cwd) - self.assertEqual(self.dst.getnames(), [], "added the archive to itself") + def _test_modes(self, testfunc): + testfunc(tarname, "r") + testfunc(tarname, "r:") + testfunc(tarname, "r:*") + testfunc(tarname, "r|") + testfunc(tarname, "r|*") + if gzip: + self.assertRaises(tarfile.ReadError, tarfile.open, tarname, mode="r:gz") + self.assertRaises(tarfile.ReadError, tarfile.open, tarname, mode="r|gz") + self.assertRaises(tarfile.ReadError, tarfile.open, gzipname, mode="r:") + self.assertRaises(tarfile.ReadError, tarfile.open, gzipname, mode="r|") + + testfunc(gzipname, "r") + testfunc(gzipname, "r:*") + testfunc(gzipname, "r:gz") + testfunc(gzipname, "r|*") + testfunc(gzipname, "r|gz") -class AppendTest(unittest.TestCase): - # Test append mode (cp. patch #1652681). + if bz2: + self.assertRaises(tarfile.ReadError, tarfile.open, tarname, mode="r:bz2") + self.assertRaises(tarfile.ReadError, tarfile.open, tarname, mode="r|bz2") + self.assertRaises(tarfile.ReadError, tarfile.open, bz2name, mode="r:") + self.assertRaises(tarfile.ReadError, tarfile.open, bz2name, mode="r|") + + testfunc(bz2name, "r") + testfunc(bz2name, "r:*") + testfunc(bz2name, "r:bz2") + testfunc(bz2name, "r|*") + testfunc(bz2name, "r|bz2") + + def test_detect_file(self): + self._test_modes(self._testfunc_file) + + def test_detect_fileobj(self): + self._test_modes(self._testfunc_fileobj) + + +class MemberReadTest(ReadTest): + + def _test_member(self, tarinfo, chksum=None, **kwargs): + if chksum is not None: + self.assert_(md5sum(self.tar.extractfile(tarinfo).read()) == chksum, + "wrong md5sum for %s" % tarinfo.name) + + kwargs["mtime"] = 07606136617 + kwargs["uid"] = 1000 + kwargs["gid"] = 100 + if "old-v7" not in tarinfo.name: + # V7 tar can't handle alphabetic owners. + kwargs["uname"] = "tarfile" + kwargs["gname"] = "tarfile" + for k, v in kwargs.items(): + self.assert_(getattr(tarinfo, k) == v, + "wrong value in %s field of %s" % (k, tarinfo.name)) + + def test_find_regtype(self): + tarinfo = self.tar.getmember("ustar/regtype") + self._test_member(tarinfo, size=7011, chksum=md5_regtype) + + def test_find_conttype(self): + tarinfo = self.tar.getmember("ustar/conttype") + self._test_member(tarinfo, size=7011, chksum=md5_regtype) + + def test_find_dirtype(self): + tarinfo = self.tar.getmember("ustar/dirtype") + self._test_member(tarinfo, size=0) + + def test_find_dirtype_with_size(self): + tarinfo = self.tar.getmember("ustar/dirtype-with-size") + self._test_member(tarinfo, size=255) + + def test_find_lnktype(self): + tarinfo = self.tar.getmember("ustar/lnktype") + self._test_member(tarinfo, size=0, linkname="ustar/regtype") + + def test_find_symtype(self): + tarinfo = self.tar.getmember("ustar/symtype") + self._test_member(tarinfo, size=0, linkname="regtype") + + def test_find_blktype(self): + tarinfo = self.tar.getmember("ustar/blktype") + self._test_member(tarinfo, size=0, devmajor=3, devminor=0) + + def test_find_chrtype(self): + tarinfo = self.tar.getmember("ustar/chrtype") + self._test_member(tarinfo, size=0, devmajor=1, devminor=3) + + def test_find_fifotype(self): + tarinfo = self.tar.getmember("ustar/fifotype") + self._test_member(tarinfo, size=0) + + def test_find_sparse(self): + tarinfo = self.tar.getmember("ustar/sparse") + self._test_member(tarinfo, size=86016, chksum=md5_sparse) + + def test_find_umlauts(self): + tarinfo = self.tar.getmember("ustar/umlauts-???????") + self._test_member(tarinfo, size=7011, chksum=md5_regtype) + + def test_find_ustar_longname(self): + name = "ustar/" + "12345/" * 39 + "1234567/longname" + self.assert_(name in self.tar.getnames()) + + def test_find_regtype_oldv7(self): + tarinfo = self.tar.getmember("misc/regtype-old-v7") + self._test_member(tarinfo, size=7011, chksum=md5_regtype) + + def test_find_pax_umlauts(self): + self.tar = tarfile.open(self.tarname, mode=self.mode, encoding="iso8859-1") + tarinfo = self.tar.getmember("pax/umlauts-???????") + self._test_member(tarinfo, size=7011, chksum=md5_regtype) + + +class LongnameTest(ReadTest): + + def test_read_longname(self): + # Test reading of longname (bug #1471427). + name = self.subdir + "/" + "123/" * 125 + "longname" + try: + tarinfo = self.tar.getmember(name) + except KeyError: + self.fail("longname not found") + self.assert_(tarinfo.type != tarfile.DIRTYPE, "read longname as dirtype") - def setUp(self): - self.tarname = tmpname() - if os.path.exists(self.tarname): - os.remove(self.tarname) + def test_read_longlink(self): + longname = self.subdir + "/" + "123/" * 125 + "longname" + longlink = self.subdir + "/" + "123/" * 125 + "longlink" + try: + tarinfo = self.tar.getmember(longlink) + except KeyError: + self.fail("longlink not found") + self.assert_(tarinfo.linkname == longname, "linkname wrong") - def _add_testfile(self, fileobj=None): - tar = tarfile.open(self.tarname, "a", fileobj=fileobj) - tar.addfile(tarfile.TarInfo("bar")) + def test_truncated_longname(self): + longname = self.subdir + "/" + "123/" * 125 + "longname" + tarinfo = self.tar.getmember(longname) + offset = tarinfo.offset + self.tar.fileobj.seek(offset) + fobj = StringIO.StringIO(self.tar.fileobj.read(1536)) + self.assertRaises(tarfile.ReadError, tarfile.open, name="foo.tar", fileobj=fobj) + + +class GNUReadTest(LongnameTest): + + subdir = "gnu" + + def test_sparse_file(self): + tarinfo1 = self.tar.getmember("ustar/sparse") + fobj1 = self.tar.extractfile(tarinfo1) + tarinfo2 = self.tar.getmember("gnu/sparse") + fobj2 = self.tar.extractfile(tarinfo2) + self.assert_(fobj1.read() == fobj2.read(), + "sparse file extraction failed") + + +class PaxReadTest(ReadTest): + + subdir = "pax" + + def test_pax_globheaders(self): + tar = tarfile.open(tarname, encoding="iso8859-1") + tarinfo = tar.getmember("pax/regtype1") + self.assertEqual(tarinfo.uname, "foo") + self.assertEqual(tarinfo.gname, "bar") + self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"), "???????") + + tarinfo = tar.getmember("pax/regtype2") + self.assertEqual(tarinfo.uname, "") + self.assertEqual(tarinfo.gname, "bar") + self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"), "???????") + + tarinfo = tar.getmember("pax/regtype3") + self.assertEqual(tarinfo.uname, "tarfile") + self.assertEqual(tarinfo.gname, "tarfile") + self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"), "???????") + + +class WriteTest(unittest.TestCase): + + mode = "w:" + + def test_100_char_name(self): + # The name field in a tar header stores strings of at most 100 chars. + # If a string is shorter than 100 chars it has to be padded with '\0', + # which implies that a string of exactly 100 chars is stored without + # a trailing '\0'. + name = "0123456789" * 10 + tar = tarfile.open(tmpname, self.mode) + t = tarfile.TarInfo(name) + tar.addfile(t) tar.close() - def _create_testtar(self): - src = tarfile.open(tarname()) - t = src.getmember("0-REGTYPE") - t.name = "foo" - f = src.extractfile(t) - tar = tarfile.open(self.tarname, "w") - tar.addfile(t, f) + tar = tarfile.open(tmpname) + self.assert_(tar.getnames()[0] == name, + "failed to store 100 char filename") tar.close() - def _test(self, names=["bar"], fileobj=None): - tar = tarfile.open(self.tarname, fileobj=fileobj) - self.assert_(tar.getnames() == names) - - def test_non_existing(self): - self._add_testfile() - self._test() - - def test_empty(self): - open(self.tarname, "wb").close() - self._add_testfile() - self._test() - - def test_empty_fileobj(self): - fobj = StringIO.StringIO() - self._add_testfile(fobj) - fobj.seek(0) - self._test(fileobj=fobj) - - def test_fileobj(self): - self._create_testtar() - data = open(self.tarname, "rb").read() - fobj = StringIO.StringIO(data) - self._add_testfile(fobj) - fobj.seek(0) - self._test(names=["foo", "bar"], fileobj=fobj) - - def test_existing(self): - self._create_testtar() - self._add_testfile() - self._test(names=["foo", "bar"]) - - -class Write100Test(BaseTest): - # The name field in a tar header stores strings of at most 100 chars. - # If a string is shorter than 100 chars it has to be padded with '\0', - # which implies that a string of exactly 100 chars is stored without - # a trailing '\0'. + def test_tar_size(self): + # Test for bug #1013882. + tar = tarfile.open(tmpname, self.mode) + path = os.path.join(TEMPDIR, "file") + fobj = open(path, "wb") + fobj.write("aaa") + fobj.close() + tar.add(path) + tar.close() + self.assert_(os.path.getsize(tmpname) > 0, + "tarfile is empty") - def setUp(self): - self.name = "01234567890123456789012345678901234567890123456789" - self.name += "01234567890123456789012345678901234567890123456789" + # The test_*_size tests test for bug #1167128. + def test_file_size(self): + tar = tarfile.open(tmpname, self.mode) - self.tar = tarfile.open(tmpname(), "w") - t = tarfile.TarInfo(self.name) - self.tar.addfile(t) - self.tar.close() + path = os.path.join(TEMPDIR, "file") + fobj = open(path, "wb") + fobj.close() + tarinfo = tar.gettarinfo(path) + self.assertEqual(tarinfo.size, 0) - self.tar = tarfile.open(tmpname()) + fobj = open(path, "wb") + fobj.write("aaa") + fobj.close() + tarinfo = tar.gettarinfo(path) + self.assertEqual(tarinfo.size, 3) - def tearDown(self): - self.tar.close() + tar.close() - def test(self): - self.assertEqual(self.tar.getnames()[0], self.name, - "failed to store 100 char filename") + def test_directory_size(self): + path = os.path.join(TEMPDIR, "directory") + os.mkdir(path) + try: + tar = tarfile.open(tmpname, self.mode) + tarinfo = tar.gettarinfo(path) + self.assertEqual(tarinfo.size, 0) + finally: + os.rmdir(path) + def test_link_size(self): + if hasattr(os, "link"): + link = os.path.join(TEMPDIR, "link") + target = os.path.join(TEMPDIR, "link_target") + open(target, "wb").close() + os.link(target, link) + try: + tar = tarfile.open(tmpname, self.mode) + tarinfo = tar.gettarinfo(link) + self.assertEqual(tarinfo.size, 0) + finally: + os.remove(target) + os.remove(link) -class WriteSize0Test(BaseTest): - mode = 'w' + def test_symlink_size(self): + if hasattr(os, "symlink"): + path = os.path.join(TEMPDIR, "symlink") + os.symlink("link_target", path) + try: + tar = tarfile.open(tmpname, self.mode) + tarinfo = tar.gettarinfo(path) + self.assertEqual(tarinfo.size, 0) + finally: + os.remove(path) - def setUp(self): - self.tmpdir = dirname() - self.dstname = tmpname() - self.dst = tarfile.open(self.dstname, "w") + def test_add_self(self): + # Test for #1257255. + dstname = os.path.abspath(tmpname) - def tearDown(self): - self.dst.close() + tar = tarfile.open(tmpname, self.mode) + self.assert_(tar.name == dstname, "archive name must be absolute") - def test_file(self): - path = os.path.join(self.tmpdir, "file") - f = open(path, "w") - f.close() - tarinfo = self.dst.gettarinfo(path) - self.assertEqual(tarinfo.size, 0) - f = open(path, "w") - f.write("aaa") - f.close() - tarinfo = self.dst.gettarinfo(path) - self.assertEqual(tarinfo.size, 3) + tar.add(dstname) + self.assert_(tar.getnames() == [], "added the archive to itself") - def test_directory(self): - path = os.path.join(self.tmpdir, "directory") - if os.path.exists(path): - # This shouldn't be necessary, but is if a previous - # run was killed in mid-stream. - shutil.rmtree(path) - os.mkdir(path) - tarinfo = self.dst.gettarinfo(path) - self.assertEqual(tarinfo.size, 0) + cwd = os.getcwd() + os.chdir(TEMPDIR) + tar.add(dstname) + os.chdir(cwd) + self.assert_(tar.getnames() == [], "added the archive to itself") - def test_symlink(self): - if hasattr(os, "symlink"): - path = os.path.join(self.tmpdir, "symlink") - os.symlink("link_target", path) - tarinfo = self.dst.gettarinfo(path) - self.assertEqual(tarinfo.size, 0) +class StreamWriteTest(unittest.TestCase): -class WriteStreamTest(WriteTest): - sep = '|' + mode = "w|" - def test_padding(self): - self.dst.close() + def test_stream_padding(self): + # Test for bug #1543303. + tar = tarfile.open(tmpname, self.mode) + tar.close() - if self.comp == "gz": - f = gzip.GzipFile(self.dstname) - s = f.read() - f.close() - elif self.comp == "bz2": - f = bz2.BZ2Decompressor() - s = open(self.dstname).read() - s = f.decompress(s) - self.assertEqual(len(f.unused_data), 0, "trailing data") + if self.mode.endswith("gz"): + fobj = gzip.GzipFile(tmpname) + data = fobj.read() + fobj.close() + elif self.mode.endswith("bz2"): + dec = bz2.BZ2Decompressor() + data = open(tmpname, "rb").read() + data = dec.decompress(data) + self.assert_(len(dec.unused_data) == 0, + "found trailing data") else: - f = open(self.dstname) - s = f.read() - f.close() + fobj = open(tmpname, "rb") + data = fobj.read() + fobj.close() - self.assertEqual(s.count("\0"), tarfile.RECORDSIZE, + self.assert_(data.count("\0") == tarfile.RECORDSIZE, "incorrect zero padding") -class WriteGNULongTest(unittest.TestCase): - """This testcase checks for correct creation of GNU Longname - and Longlink extensions. - - It creates a tarfile and adds empty members with either - long names, long linknames or both and compares the size - of the tarfile with the expected size. - - It checks for SF bug #812325 in TarFile._create_gnulong(). - - While I was writing this testcase, I noticed a second bug - in the same method: - Long{names,links} weren't null-terminated which lead to - bad tarfiles when their length was a multiple of 512. This - is tested as well. - """ +class GNUWriteTest(unittest.TestCase): + # This testcase checks for correct creation of GNU Longname + # and Longlink extended headers (cp. bug #812325). def _length(self, s): blocks, remainder = divmod(len(s) + 1, 512) @@ -474,19 +573,17 @@ return blocks * 512 def _calc_size(self, name, link=None): - # initial tar header + # Initial tar header count = 512 if len(name) > tarfile.LENGTH_NAME: - # gnu longname extended header + longname + # GNU longname extended header + longname count += 512 count += self._length(name) - if link is not None and len(link) > tarfile.LENGTH_LINK: - # gnu longlink extended header + longlink + # GNU longlink extended header + longlink count += 512 count += self._length(link) - return count def _test(self, name, link=None): @@ -495,17 +592,17 @@ tarinfo.linkname = link tarinfo.type = tarfile.LNKTYPE - tar = tarfile.open(tmpname(), "w") - tar.posix = False + tar = tarfile.open(tmpname, "w") + tar.format = tarfile.GNU_FORMAT tar.addfile(tarinfo) v1 = self._calc_size(name, link) v2 = tar.offset - self.assertEqual(v1, v2, "GNU longname/longlink creation failed") + self.assert_(v1 == v2, "GNU longname/longlink creation failed") tar.close() - tar = tarfile.open(tmpname()) + tar = tarfile.open(tmpname) member = tar.next() self.failIf(member is None, "unable to read longname member") self.assert_(tarinfo.name == member.name and \ @@ -542,268 +639,351 @@ self._test(("longnam/" * 127) + "longname_", ("longlnk/" * 127) + "longlink_") -class ReadGNULongTest(unittest.TestCase): + +class HardlinkTest(unittest.TestCase): + # Test the creation of LNKTYPE (hardlink) members in an archive. def setUp(self): - self.tar = tarfile.open(tarname()) + self.foo = os.path.join(TEMPDIR, "foo") + self.bar = os.path.join(TEMPDIR, "bar") + + fobj = open(self.foo, "wb") + fobj.write("foo") + fobj.close() + + os.link(self.foo, self.bar) + + self.tar = tarfile.open(tmpname, "w") + self.tar.add(self.foo) def tearDown(self): - self.tar.close() + os.remove(self.foo) + os.remove(self.bar) - def test_1471427(self): - """Test reading of longname (bug #1471427). - """ - name = "test/" * 20 + "0-REGTYPE" - try: - tarinfo = self.tar.getmember(name) - except KeyError: - tarinfo = None - self.assert_(tarinfo is not None, "longname not found") - self.assert_(tarinfo.type != tarfile.DIRTYPE, "read longname as dirtype") + def test_add_twice(self): + # The same name will be added as a REGTYPE every + # time regardless of st_nlink. + tarinfo = self.tar.gettarinfo(self.foo) + self.assert_(tarinfo.type == tarfile.REGTYPE, + "add file as regular failed") - def test_read_name(self): - name = ("0-LONGNAME-" * 10)[:101] - try: - tarinfo = self.tar.getmember(name) - except KeyError: - tarinfo = None - self.assert_(tarinfo is not None, "longname not found") + def test_add_hardlink(self): + tarinfo = self.tar.gettarinfo(self.bar) + self.assert_(tarinfo.type == tarfile.LNKTYPE, + "add file as hardlink failed") - def test_read_link(self): - link = ("1-LONGLINK-" * 10)[:101] - name = ("0-LONGNAME-" * 10)[:101] - try: - tarinfo = self.tar.getmember(link) - except KeyError: - tarinfo = None - self.assert_(tarinfo is not None, "longlink not found") - self.assert_(tarinfo.linkname == name, "linkname wrong") + def test_dereference_hardlink(self): + self.tar.dereference = True + tarinfo = self.tar.gettarinfo(self.bar) + self.assert_(tarinfo.type == tarfile.REGTYPE, + "dereferencing hardlink failed") - def test_truncated_longname(self): - f = open(tarname()) - fobj = StringIO.StringIO(f.read(1024)) - f.close() - tar = tarfile.open(name="foo.tar", fileobj=fobj) - self.assert_(len(tar.getmembers()) == 0, "") - tar.close() +class PaxWriteTest(GNUWriteTest): -class ExtractHardlinkTest(BaseTest): + def _test(self, name, link=None): + # See GNUWriteTest. + tarinfo = tarfile.TarInfo(name) + if link: + tarinfo.linkname = link + tarinfo.type = tarfile.LNKTYPE - def test_hardlink(self): - """Test hardlink extraction (bug #857297) - """ - # Prevent errors from being caught - self.tar.errorlevel = 1 + tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT) + tar.addfile(tarinfo) + tar.close() - self.tar.extract("0-REGTYPE", dirname()) - try: - # Extract 1-LNKTYPE which is a hardlink to 0-REGTYPE - self.tar.extract("1-LNKTYPE", dirname()) - except EnvironmentError as e: - import errno - if e.errno == errno.ENOENT: - self.fail("hardlink not extracted properly") + tar = tarfile.open(tmpname) + if link: + l = tar.getmembers()[0].linkname + self.assert_(link == l, "PAX longlink creation failed") + else: + n = tar.getmembers()[0].name + self.assert_(name == n, "PAX longname creation failed") -class CreateHardlinkTest(BaseTest): - """Test the creation of LNKTYPE (hardlink) members in an archive. - In this respect tarfile.py mimics the behaviour of GNU tar: If - a file has a st_nlink > 1, it will be added a REGTYPE member - only the first time. - """ + def test_iso8859_15_filename(self): + self._test_unicode_filename("iso8859-15") - def setUp(self): - self.tar = tarfile.open(tmpname(), "w") + def test_utf8_filename(self): + self._test_unicode_filename("utf8") - self.foo = os.path.join(dirname(), "foo") - self.bar = os.path.join(dirname(), "bar") + def test_utf16_filename(self): + self._test_unicode_filename("utf16") + + def _test_unicode_filename(self, encoding): + tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT) + name = u"\u20ac".encode(encoding) # Euro sign + tar.encoding = encoding + tar.addfile(tarfile.TarInfo(name)) + tar.close() - if os.path.exists(self.foo): - os.remove(self.foo) - if os.path.exists(self.bar): - os.remove(self.bar) - - f = open(self.foo, "w") - f.write("foo") - f.close() - self.tar.add(self.foo) + tar = tarfile.open(tmpname, encoding=encoding) + self.assertEqual(tar.getmembers()[0].name, name) + tar.close() - def test_add_twice(self): - # If st_nlink == 1 then the same file will be added as - # REGTYPE every time. - tarinfo = self.tar.gettarinfo(self.foo) - self.assertEqual(tarinfo.type, tarfile.REGTYPE, - "add file as regular failed") + def test_unicode_filename_error(self): + # The euro sign filename cannot be translated to iso8859-1 encoding. + tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT, encoding="utf8") + name = u"\u20ac".encode("utf8") # Euro sign + tar.addfile(tarfile.TarInfo(name)) + tar.close() - def test_add_hardlink(self): - # If st_nlink > 1 then the same file will be added as - # LNKTYPE. - os.link(self.foo, self.bar) - tarinfo = self.tar.gettarinfo(self.foo) - self.assertEqual(tarinfo.type, tarfile.LNKTYPE, - "add file as hardlink failed") + self.assertRaises(UnicodeError, tarfile.open, tmpname, encoding="iso8859-1") - tarinfo = self.tar.gettarinfo(self.bar) - self.assertEqual(tarinfo.type, tarfile.LNKTYPE, - "add file as hardlink failed") + def test_pax_headers(self): + self._test_pax_headers({"foo": "bar", "uid": 0, "mtime": 1.23}) - def test_dereference_hardlink(self): - self.tar.dereference = True - os.link(self.foo, self.bar) - tarinfo = self.tar.gettarinfo(self.bar) - self.assertEqual(tarinfo.type, tarfile.REGTYPE, - "dereferencing hardlink failed") + self._test_pax_headers({"euro": u"\u20ac".encode("utf8")}) + self._test_pax_headers({"euro": u"\u20ac"}, + {"euro": u"\u20ac".encode("utf8")}) -# Gzip TestCases -class ReadTestGzip(ReadTest): - comp = "gz" -class ReadStreamTestGzip(ReadStreamTest): - comp = "gz" -class WriteTestGzip(WriteTest): - comp = "gz" -class WriteStreamTestGzip(WriteStreamTest): - comp = "gz" -class ReadDetectTestGzip(ReadDetectTest): - comp = "gz" -class ReadDetectFileobjTestGzip(ReadDetectFileobjTest): - comp = "gz" -class ReadAsteriskTestGzip(ReadAsteriskTest): - comp = "gz" -class ReadStreamAsteriskTestGzip(ReadStreamAsteriskTest): - comp = "gz" - -# Filemode test cases - -class FileModeTest(unittest.TestCase): - def test_modes(self): - self.assertEqual(tarfile.filemode(0755), '-rwxr-xr-x') - self.assertEqual(tarfile.filemode(07111), '---s--s--t') + self._test_pax_headers({u"\u20ac": "euro"}, + {u"\u20ac".encode("utf8"): "euro"}) -class HeaderErrorTest(unittest.TestCase): + def _test_pax_headers(self, pax_headers, cmp_headers=None): + if cmp_headers is None: + cmp_headers = pax_headers + + tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT, \ + pax_headers=pax_headers, encoding="utf8") + tar.addfile(tarfile.TarInfo("test")) + tar.close() + + tar = tarfile.open(tmpname, encoding="utf8") + self.assertEqual(tar.pax_headers, cmp_headers) def test_truncated_header(self): - self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "") - self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "filename\0") - self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 511) - self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 513) - - def test_empty_header(self): - self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 512) - - def test_invalid_header(self): - buf = tarfile.TarInfo("filename").tobuf() - buf = buf[:148] + "foo\0\0\0\0\0" + buf[156:] # invalid number field. - self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, buf) - - def test_bad_checksum(self): - buf = tarfile.TarInfo("filename").tobuf() - b = buf[:148] + " " + buf[156:] # clear the checksum field. - self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, b) - b = "a" + buf[1:] # manipulate the buffer, so checksum won't match. - self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, b) + tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT) + tarinfo = tarfile.TarInfo("123/" * 126 + "longname") + tar.addfile(tarinfo) + tar.close() -class OpenFileobjTest(BaseTest): - # Test for SF bug #1496501. + # Simulate a premature EOF. + open(tmpname, "rb+").truncate(1536) + tar = tarfile.open(tmpname) + self.assertEqual(tar.getmembers(), []) - def test_opener(self): - fobj = StringIO.StringIO("foo\n") - try: - tarfile.open("", "r", fileobj=fobj) - except tarfile.ReadError: - self.assertEqual(fobj.tell(), 0, "fileobj's position has moved") -if bz2: - # Bzip2 TestCases - class ReadTestBzip2(ReadTestGzip): - comp = "bz2" - class ReadStreamTestBzip2(ReadStreamTestGzip): - comp = "bz2" - class WriteTestBzip2(WriteTest): - comp = "bz2" - class WriteStreamTestBzip2(WriteStreamTestGzip): - comp = "bz2" - class ReadDetectTestBzip2(ReadDetectTest): - comp = "bz2" - class ReadDetectFileobjTestBzip2(ReadDetectFileobjTest): - comp = "bz2" - class ReadAsteriskTestBzip2(ReadAsteriskTest): - comp = "bz2" - class ReadStreamAsteriskTestBzip2(ReadStreamAsteriskTest): - comp = "bz2" - -# If importing gzip failed, discard the Gzip TestCases. -if not gzip: - del ReadTestGzip - del ReadStreamTestGzip - del WriteTestGzip - del WriteStreamTestGzip +class AppendTest(unittest.TestCase): + # Test append mode (cp. patch #1652681). -def test_main(): - # Create archive. - f = open(tarname(), "rb") - fguts = f.read() - f.close() - if gzip: - # create testtar.tar.gz - tar = gzip.open(tarname("gz"), "wb") - tar.write(fguts) + def setUp(self): + self.tarname = tmpname + if os.path.exists(self.tarname): + os.remove(self.tarname) + + def _add_testfile(self, fileobj=None): + tar = tarfile.open(self.tarname, "a", fileobj=fileobj) + tar.addfile(tarfile.TarInfo("bar")) tar.close() - if bz2: - # create testtar.tar.bz2 - tar = bz2.BZ2File(tarname("bz2"), "wb") - tar.write(fguts) + + def _create_testtar(self, mode="w:"): + src = tarfile.open(tarname, encoding="iso8859-1") + t = src.getmember("ustar/regtype") + t.name = "foo" + f = src.extractfile(t) + tar = tarfile.open(self.tarname, mode) + tar.addfile(t, f) tar.close() + def _test(self, names=["bar"], fileobj=None): + tar = tarfile.open(self.tarname, fileobj=fileobj) + self.assertEqual(tar.getnames(), names) + + def test_non_existing(self): + self._add_testfile() + self._test() + + def test_empty(self): + open(self.tarname, "w").close() + self._add_testfile() + self._test() + + def test_empty_fileobj(self): + fobj = StringIO.StringIO() + self._add_testfile(fobj) + fobj.seek(0) + self._test(fileobj=fobj) + + def test_fileobj(self): + self._create_testtar() + data = open(self.tarname).read() + fobj = StringIO.StringIO(data) + self._add_testfile(fobj) + fobj.seek(0) + self._test(names=["foo", "bar"], fileobj=fobj) + + def test_existing(self): + self._create_testtar() + self._add_testfile() + self._test(names=["foo", "bar"]) + + def test_append_gz(self): + if gzip is None: + return + self._create_testtar("w:gz") + self.assertRaises(tarfile.ReadError, tarfile.open, tmpname, "a") + + def test_append_bz2(self): + if bz2 is None: + return + self._create_testtar("w:bz2") + self.assertRaises(tarfile.ReadError, tarfile.open, tmpname, "a") + + +class LimitsTest(unittest.TestCase): + + def test_ustar_limits(self): + # 100 char name + tarinfo = tarfile.TarInfo("0123456789" * 10) + tarinfo.create_ustar_header() + + # 101 char name that cannot be stored + tarinfo = tarfile.TarInfo("0123456789" * 10 + "0") + self.assertRaises(ValueError, tarinfo.create_ustar_header) + + # 256 char name with a slash at pos 156 + tarinfo = tarfile.TarInfo("123/" * 62 + "longname") + tarinfo.create_ustar_header() + + # 256 char name that cannot be stored + tarinfo = tarfile.TarInfo("1234567/" * 31 + "longname") + self.assertRaises(ValueError, tarinfo.create_ustar_header) + + # 512 char name + tarinfo = tarfile.TarInfo("123/" * 126 + "longname") + self.assertRaises(ValueError, tarinfo.create_ustar_header) + + # 512 char linkname + tarinfo = tarfile.TarInfo("longlink") + tarinfo.linkname = "123/" * 126 + "longname" + self.assertRaises(ValueError, tarinfo.create_ustar_header) + + # uid > 8 digits + tarinfo = tarfile.TarInfo("name") + tarinfo.uid = 010000000 + self.assertRaises(ValueError, tarinfo.create_ustar_header) + + def test_gnu_limits(self): + tarinfo = tarfile.TarInfo("123/" * 126 + "longname") + tarinfo.create_gnu_header() + + tarinfo = tarfile.TarInfo("longlink") + tarinfo.linkname = "123/" * 126 + "longname" + tarinfo.create_gnu_header() + + # uid >= 256 ** 7 + tarinfo = tarfile.TarInfo("name") + tarinfo.uid = 04000000000000000000 + self.assertRaises(ValueError, tarinfo.create_gnu_header) + + def test_pax_limits(self): + # A 256 char name that can be stored without an extended header. + tarinfo = tarfile.TarInfo("123/" * 62 + "longname") + self.assert_(len(tarinfo.create_pax_header("utf8")) == 512, + "create_pax_header attached superfluous extended header") + + tarinfo = tarfile.TarInfo("123/" * 126 + "longname") + tarinfo.create_pax_header("utf8") + + tarinfo = tarfile.TarInfo("longlink") + tarinfo.linkname = "123/" * 126 + "longname" + tarinfo.create_pax_header("utf8") + + tarinfo = tarfile.TarInfo("name") + tarinfo.uid = 04000000000000000000 + tarinfo.create_pax_header("utf8") + + +class GzipMiscReadTest(MiscReadTest): + tarname = gzipname + mode = "r:gz" +class GzipUstarReadTest(UstarReadTest): + tarname = gzipname + mode = "r:gz" +class GzipStreamReadTest(StreamReadTest): + tarname = gzipname + mode = "r|gz" +class GzipWriteTest(WriteTest): + mode = "w:gz" +class GzipStreamWriteTest(StreamWriteTest): + mode = "w|gz" + + +class Bz2MiscReadTest(MiscReadTest): + tarname = bz2name + mode = "r:bz2" +class Bz2UstarReadTest(UstarReadTest): + tarname = bz2name + mode = "r:bz2" +class Bz2StreamReadTest(StreamReadTest): + tarname = bz2name + mode = "r|bz2" +class Bz2WriteTest(WriteTest): + mode = "w:bz2" +class Bz2StreamWriteTest(StreamWriteTest): + mode = "w|bz2" + +def test_main(): + if not os.path.exists(TEMPDIR): + os.mkdir(TEMPDIR) + tests = [ - FileModeTest, - HeaderErrorTest, - OpenFileobjTest, - ReadTest, - ReadStreamTest, - ReadDetectTest, - ReadDetectFileobjTest, - ReadAsteriskTest, - ReadStreamAsteriskTest, + UstarReadTest, + MiscReadTest, + StreamReadTest, + DetectReadTest, + MemberReadTest, + GNUReadTest, + PaxReadTest, WriteTest, + StreamWriteTest, + GNUWriteTest, + PaxWriteTest, AppendTest, - Write100Test, - WriteSize0Test, - WriteStreamTest, - WriteGNULongTest, - ReadGNULongTest, + LimitsTest, ] if hasattr(os, "link"): - tests.append(ExtractHardlinkTest) - tests.append(CreateHardlinkTest) + tests.append(HardlinkTest) + + fobj = open(tarname, "rb") + data = fobj.read() + fobj.close() if gzip: - tests.extend([ - ReadTestGzip, ReadStreamTestGzip, - WriteTestGzip, WriteStreamTestGzip, - ReadDetectTestGzip, ReadDetectFileobjTestGzip, - ReadAsteriskTestGzip, ReadStreamAsteriskTestGzip - ]) + # Create testtar.tar.gz and add gzip-specific tests. + tar = gzip.open(gzipname, "wb") + tar.write(data) + tar.close() + + tests += [ + GzipMiscReadTest, + GzipUstarReadTest, + GzipStreamReadTest, + GzipWriteTest, + GzipStreamWriteTest, + ] if bz2: - tests.extend([ - ReadTestBzip2, ReadStreamTestBzip2, - WriteTestBzip2, WriteStreamTestBzip2, - ReadDetectTestBzip2, ReadDetectFileobjTestBzip2, - ReadAsteriskTestBzip2, ReadStreamAsteriskTestBzip2 - ]) + # Create testtar.tar.bz2 and add bz2-specific tests. + tar = bz2.BZ2File(bz2name, "wb") + tar.write(data) + tar.close() + + tests += [ + Bz2MiscReadTest, + Bz2UstarReadTest, + Bz2StreamReadTest, + Bz2WriteTest, + Bz2StreamWriteTest, + ] + try: test_support.run_unittest(*tests) finally: - if gzip: - os.remove(tarname("gz")) - if bz2: - os.remove(tarname("bz2")) - if os.path.exists(dirname()): - shutil.rmtree(dirname()) - if os.path.exists(tmpname()): - os.remove(tmpname()) + if os.path.exists(TEMPDIR): + shutil.rmtree(TEMPDIR) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_tempfile.py ============================================================================== --- python/branches/p3yk/Lib/test/test_tempfile.py (original) +++ python/branches/p3yk/Lib/test/test_tempfile.py Fri Apr 27 21:54:29 2007 @@ -81,7 +81,8 @@ "gettempprefix" : 1, "gettempdir" : 1, "tempdir" : 1, - "template" : 1 + "template" : 1, + "SpooledTemporaryFile" : 1 } unexp = [] @@ -561,11 +562,12 @@ class test_NamedTemporaryFile(TC): """Test NamedTemporaryFile().""" - def do_create(self, dir=None, pre="", suf=""): + def do_create(self, dir=None, pre="", suf="", delete=True): if dir is None: dir = tempfile.gettempdir() try: - file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf) + file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf, + delete=delete) except: self.failOnException("NamedTemporaryFile") @@ -599,6 +601,22 @@ finally: os.rmdir(dir) + def test_dis_del_on_close(self): + # Tests that delete-on-close can be disabled + dir = tempfile.mkdtemp() + tmp = None + try: + f = tempfile.NamedTemporaryFile(dir=dir, delete=False) + tmp = f.name + f.write('blat') + f.close() + self.failUnless(os.path.exists(f.name), + "NamedTemporaryFile %s missing after close" % f.name) + finally: + if tmp is not None: + os.unlink(tmp) + os.rmdir(dir) + def test_multiple_close(self): # A NamedTemporaryFile can be closed many times without error @@ -615,6 +633,107 @@ test_classes.append(test_NamedTemporaryFile) +class test_SpooledTemporaryFile(TC): + """Test SpooledTemporaryFile().""" + + def do_create(self, max_size=0, dir=None, pre="", suf=""): + if dir is None: + dir = tempfile.gettempdir() + try: + file = tempfile.SpooledTemporaryFile(max_size=max_size, dir=dir, prefix=pre, suffix=suf) + except: + self.failOnException("SpooledTemporaryFile") + + return file + + + def test_basic(self): + # SpooledTemporaryFile can create files + f = self.do_create() + self.failIf(f._rolled) + f = self.do_create(max_size=100, pre="a", suf=".txt") + self.failIf(f._rolled) + + def test_del_on_close(self): + # A SpooledTemporaryFile is deleted when closed + dir = tempfile.mkdtemp() + try: + f = tempfile.SpooledTemporaryFile(max_size=10, dir=dir) + self.failIf(f._rolled) + f.write('blat ' * 5) + self.failUnless(f._rolled) + filename = f.name + f.close() + self.failIf(os.path.exists(filename), + "SpooledTemporaryFile %s exists after close" % filename) + finally: + os.rmdir(dir) + + def test_rewrite_small(self): + # A SpooledTemporaryFile can be written to multiple within the max_size + f = self.do_create(max_size=30) + self.failIf(f._rolled) + for i in range(5): + f.seek(0, 0) + f.write('x' * 20) + self.failIf(f._rolled) + + def test_write_sequential(self): + # A SpooledTemporaryFile should hold exactly max_size bytes, and roll + # over afterward + f = self.do_create(max_size=30) + self.failIf(f._rolled) + f.write('x' * 20) + self.failIf(f._rolled) + f.write('x' * 10) + self.failIf(f._rolled) + f.write('x') + self.failUnless(f._rolled) + + def test_sparse(self): + # A SpooledTemporaryFile that is written late in the file will extend + # when that occurs + f = self.do_create(max_size=30) + self.failIf(f._rolled) + f.seek(100, 0) + self.failIf(f._rolled) + f.write('x') + self.failUnless(f._rolled) + + def test_fileno(self): + # A SpooledTemporaryFile should roll over to a real file on fileno() + f = self.do_create(max_size=30) + self.failIf(f._rolled) + self.failUnless(f.fileno() > 0) + self.failUnless(f._rolled) + + def test_multiple_close(self): + # A SpooledTemporaryFile can be closed many times without error + f = tempfile.SpooledTemporaryFile() + f.write('abc\n') + f.close() + try: + f.close() + f.close() + except: + self.failOnException("close") + + def test_bound_methods(self): + # It should be OK to steal a bound method from a SpooledTemporaryFile + # and use it independently; when the file rolls over, those bound + # methods should continue to function + f = self.do_create(max_size=30) + read = f.read + write = f.write + seek = f.seek + + write("a" * 35) + write("b" * 35) + seek(0, 0) + self.failUnless(read(70) == 'a'*35 + 'b'*35) + +test_classes.append(test_SpooledTemporaryFile) + class test_TemporaryFile(TC): """Test TemporaryFile().""" Modified: python/branches/p3yk/Lib/test/test_textwrap.py ============================================================================== --- python/branches/p3yk/Lib/test/test_textwrap.py (original) +++ python/branches/p3yk/Lib/test/test_textwrap.py Fri Apr 27 21:54:29 2007 @@ -328,6 +328,14 @@ self.check_wrap(text, 30, [" This is a sentence with", "leading whitespace."]) + def test_no_drop_whitespace(self): + # SF patch #1581073 + text = " This is a sentence with much whitespace." + self.check_wrap(text, 10, + [" This is a", " ", "sentence ", + "with ", "much white", "space."], + drop_whitespace=False) + if test_support.have_unicode: def test_unicode(self): # *Very* simple test of wrapping Unicode strings. I'm sure Modified: python/branches/p3yk/Lib/test/test_threadedtempfile.py ============================================================================== --- python/branches/p3yk/Lib/test/test_threadedtempfile.py (original) +++ python/branches/p3yk/Lib/test/test_threadedtempfile.py Fri Apr 27 21:54:29 2007 @@ -10,22 +10,20 @@ By default, NUM_THREADS == 20 and FILES_PER_THREAD == 50. This is enough to create about 150 failures per run under Win98SE in 2.0, and runs pretty quickly. Guido reports needing to boost FILES_PER_THREAD to 500 before -provoking a 2.0 failure under Linux. Run the test alone to boost either -via cmdline switches: - --f FILES_PER_THREAD (int) --t NUM_THREADS (int) +provoking a 2.0 failure under Linux. """ -NUM_THREADS = 20 # change w/ -t option -FILES_PER_THREAD = 50 # change w/ -f option +NUM_THREADS = 20 +FILES_PER_THREAD = 50 import thread # If this fails, we can't test this module import threading -from test.test_support import TestFailed, threading_setup, threading_cleanup +import tempfile + +from test.test_support import threading_setup, threading_cleanup, run_unittest +import unittest import StringIO from traceback import print_exc -import tempfile startEvent = threading.Event() @@ -46,41 +44,36 @@ else: self.ok_count += 1 -def test_main(): - threads = [] - thread_info = threading_setup() - print("Creating") - for i in range(NUM_THREADS): - t = TempFileGreedy() - threads.append(t) - t.start() - - print("Starting") - startEvent.set() - - print("Reaping") - ok = errors = 0 - for t in threads: - t.join() - ok += t.ok_count - errors += t.error_count - if t.error_count: - print('%s errors:\n%s' % (t.getName(), t.errors.getvalue())) - - msg = "Done: errors %d ok %d" % (errors, ok) - print(msg) - if errors: - raise TestFailed(msg) +class ThreadedTempFileTest(unittest.TestCase): + def test_main(self): + threads = [] + thread_info = threading_setup() + + for i in range(NUM_THREADS): + t = TempFileGreedy() + threads.append(t) + t.start() + + startEvent.set() + + ok = 0 + errors = [] + for t in threads: + t.join() + ok += t.ok_count + if t.error_count: + errors.append(str(t.getName()) + str(t.errors.getvalue())) + + threading_cleanup(*thread_info) + + msg = "Errors: errors %d ok %d\n%s" % (len(errors), ok, + '\n'.join(errors)) + self.assertEquals(errors, [], msg) + self.assertEquals(ok, NUM_THREADS * FILES_PER_THREAD) - threading_cleanup(*thread_info) +def test_main(): + run_unittest(ThreadedTempFileTest) if __name__ == "__main__": - import sys, getopt - opts, args = getopt.getopt(sys.argv[1:], "t:f:") - for o, v in opts: - if o == "-f": - FILES_PER_THREAD = int(v) - elif o == "-t": - NUM_THREADS = int(v) test_main() Modified: python/branches/p3yk/Lib/test/test_threading_local.py ============================================================================== --- python/branches/p3yk/Lib/test/test_threading_local.py (original) +++ python/branches/p3yk/Lib/test/test_threading_local.py Fri Apr 27 21:54:29 2007 @@ -20,7 +20,7 @@ setUp=setUp, tearDown=tearDown) ) - test_support.run_suite(suite) + test_support.run_unittest(suite) if __name__ == '__main__': test_main() Modified: python/branches/p3yk/Lib/test/test_unicode.py ============================================================================== --- python/branches/p3yk/Lib/test/test_unicode.py (original) +++ python/branches/p3yk/Lib/test/test_unicode.py Fri Apr 27 21:54:29 2007 @@ -829,7 +829,7 @@ def test_main(): - test_support.run_unittest(UnicodeTest) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_unicode_file.py ============================================================================== --- python/branches/p3yk/Lib/test/test_unicode_file.py (original) +++ python/branches/p3yk/Lib/test/test_unicode_file.py Fri Apr 27 21:54:29 2007 @@ -5,7 +5,7 @@ import unicodedata import unittest -from test.test_support import run_suite, TestSkipped, TESTFN_UNICODE +from test.test_support import run_unittest, TestSkipped, TESTFN_UNICODE from test.test_support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE try: TESTFN_ENCODED = TESTFN_UNICODE.encode(TESTFN_ENCODING) @@ -205,9 +205,7 @@ False) def test_main(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestUnicodeFiles)) - run_suite(suite) + run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_unittest.py ============================================================================== --- python/branches/p3yk/Lib/test/test_unittest.py (original) +++ python/branches/p3yk/Lib/test/test_unittest.py Fri Apr 27 21:54:29 2007 @@ -1,31 +1,2302 @@ """Test script for unittest. -This just includes tests for new features. We really need a -full set of tests. +By Collin Winter + +Still need testing: + TestCase.{assert,fail}* methods (some are tested implicitly) """ +from test import test_support import unittest +from unittest import TestCase + +### Support code +################################################################ + +class LoggingResult(unittest.TestResult): + def __init__(self, log): + self._events = log + super(LoggingResult, self).__init__() + + def startTest(self, test): + self._events.append('startTest') + super(LoggingResult, self).startTest(test) + + def stopTest(self, test): + self._events.append('stopTest') + super(LoggingResult, self).stopTest(test) + + def addFailure(self, *args): + self._events.append('addFailure') + super(LoggingResult, self).addFailure(*args) + + def addError(self, *args): + self._events.append('addError') + super(LoggingResult, self).addError(*args) + +class TestEquality(object): + # Check for a valid __eq__ implementation + def test_eq(self): + for obj_1, obj_2 in self.eq_pairs: + self.assertEqual(obj_1, obj_2) + self.assertEqual(obj_2, obj_1) + + # Check for a valid __ne__ implementation + def test_ne(self): + for obj_1, obj_2 in self.ne_pairs: + self.failIfEqual(obj_1, obj_2) + self.failIfEqual(obj_2, obj_1) + +class TestHashing(object): + # Check for a valid __hash__ implementation + def test_hash(self): + for obj_1, obj_2 in self.eq_pairs: + try: + assert hash(obj_1) == hash(obj_2) + except KeyboardInterrupt: + raise + except AssertionError: + self.fail("%s and %s do not hash equal" % (obj_1, obj_2)) + except Exception as e: + self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e)) + + for obj_1, obj_2 in self.ne_pairs: + try: + assert hash(obj_1) != hash(obj_2) + except KeyboardInterrupt: + raise + except AssertionError: + self.fail("%s and %s hash equal, but shouldn't" % (obj_1, obj_2)) + except Exception as e: + self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e)) + + +################################################################ +### /Support code + +class Test_TestLoader(TestCase): + + ### Tests for TestLoader.loadTestsFromTestCase + ################################################################ + + # "Return a suite of all tests cases contained in the TestCase-derived + # class testCaseClass" + def test_loadTestsFromTestCase(self): + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foo_bar(self): pass + + tests = unittest.TestSuite([Foo('test_1'), Foo('test_2')]) + + loader = unittest.TestLoader() + self.assertEqual(loader.loadTestsFromTestCase(Foo), tests) + + # "Return a suite of all tests cases contained in the TestCase-derived + # class testCaseClass" + # + # Make sure it does the right thing even if no tests were found + def test_loadTestsFromTestCase__no_matches(self): + class Foo(unittest.TestCase): + def foo_bar(self): pass + + empty_suite = unittest.TestSuite() + + loader = unittest.TestLoader() + self.assertEqual(loader.loadTestsFromTestCase(Foo), empty_suite) + + # "Return a suite of all tests cases contained in the TestCase-derived + # class testCaseClass" + # + # What happens if loadTestsFromTestCase() is given an object + # that isn't a subclass of TestCase? Specifically, what happens + # if testCaseClass is a subclass of TestSuite? + # + # This is checked for specifically in the code, so we better add a + # test for it. + def test_loadTestsFromTestCase__TestSuite_subclass(self): + class NotATestCase(unittest.TestSuite): + pass + + loader = unittest.TestLoader() + try: + loader.loadTestsFromTestCase(NotATestCase) + except TypeError: + pass + else: + self.fail('Should raise TypeError') + + # "Return a suite of all tests cases contained in the TestCase-derived + # class testCaseClass" + # + # Make sure loadTestsFromTestCase() picks up the default test method + # name (as specified by TestCase), even though the method name does + # not match the default TestLoader.testMethodPrefix string + def test_loadTestsFromTestCase__default_method_name(self): + class Foo(unittest.TestCase): + def runTest(self): + pass + + loader = unittest.TestLoader() + # This has to be false for the test to succeed + self.failIf('runTest'.startswith(loader.testMethodPrefix)) + + suite = loader.loadTestsFromTestCase(Foo) + self.failUnless(isinstance(suite, loader.suiteClass)) + self.assertEqual(list(suite), [Foo('runTest')]) + + ################################################################ + ### /Tests for TestLoader.loadTestsFromTestCase + + ### Tests for TestLoader.loadTestsFromModule + ################################################################ + + # "This method searches `module` for classes derived from TestCase" + def test_loadTestsFromModule__TestCase_subclass(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + def test(self): + pass + m.testcase_1 = MyTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromModule(m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + expected = [loader.suiteClass([MyTestCase('test')])] + self.assertEqual(list(suite), expected) + + # "This method searches `module` for classes derived from TestCase" + # + # What happens if no tests are found (no TestCase instances)? + def test_loadTestsFromModule__no_TestCase_instances(self): + import new + m = new.module('m') + + loader = unittest.TestLoader() + suite = loader.loadTestsFromModule(m) + self.failUnless(isinstance(suite, loader.suiteClass)) + self.assertEqual(list(suite), []) + + # "This method searches `module` for classes derived from TestCase" + # + # What happens if no tests are found (TestCases instances, but no tests)? + def test_loadTestsFromModule__no_TestCase_tests(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + pass + m.testcase_1 = MyTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromModule(m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + self.assertEqual(list(suite), [loader.suiteClass()]) + + # "This method searches `module` for classes derived from TestCase"s + # + # What happens if loadTestsFromModule() is given something other + # than a module? + # + # XXX Currently, it succeeds anyway. This flexibility + # should either be documented or loadTestsFromModule() should + # raise a TypeError + # + # XXX Certain people are using this behaviour. We'll add a test for it + def test_loadTestsFromModule__not_a_module(self): + class MyTestCase(unittest.TestCase): + def test(self): + pass + + class NotAModule(object): + test_2 = MyTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromModule(NotAModule) + + reference = [unittest.TestSuite([MyTestCase('test')])] + self.assertEqual(list(suite), reference) + + ################################################################ + ### /Tests for TestLoader.loadTestsFromModule() + + ### Tests for TestLoader.loadTestsFromName() + ################################################################ + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # Is ValueError raised in response to an empty name? + def test_loadTestsFromName__empty_name(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromName('') + except ValueError as e: + self.assertEqual(str(e), "Empty module name") + else: + self.fail("TestLoader.loadTestsFromName failed to raise ValueError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # What happens when the name contains invalid characters? + def test_loadTestsFromName__malformed_name(self): + loader = unittest.TestLoader() + + # XXX Should this raise ValueError or ImportError? + try: + loader.loadTestsFromName('abc () //') + except ValueError: + pass + except ImportError: + pass + else: + self.fail("TestLoader.loadTestsFromName failed to raise ValueError") + + # "The specifier name is a ``dotted name'' that may resolve ... to a + # module" + # + # What happens when a module by that name can't be found? + def test_loadTestsFromName__unknown_module_name(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromName('sdasfasfasdf') + except ImportError as e: + self.assertEqual(str(e), "No module named sdasfasfasdf") + else: + self.fail("TestLoader.loadTestsFromName failed to raise ImportError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # What happens when the module is found, but the attribute can't? + def test_loadTestsFromName__unknown_attr_name(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromName('unittest.sdasfasfasdf') + except AttributeError as e: + self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") + else: + self.fail("TestLoader.loadTestsFromName failed to raise AttributeError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # What happens when we provide the module, but the attribute can't be + # found? + def test_loadTestsFromName__relative_unknown_name(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromName('sdasfasfasdf', unittest) + except AttributeError as e: + self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") + else: + self.fail("TestLoader.loadTestsFromName failed to raise AttributeError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # ... + # "The method optionally resolves name relative to the given module" + # + # Does loadTestsFromName raise ValueError when passed an empty + # name relative to a provided module? + # + # XXX Should probably raise a ValueError instead of an AttributeError + def test_loadTestsFromName__relative_empty_name(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromName('', unittest) + except AttributeError as e: + pass + else: + self.fail("Failed to raise AttributeError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # ... + # "The method optionally resolves name relative to the given module" + # + # What happens when an impossible name is given, relative to the provided + # `module`? + def test_loadTestsFromName__relative_malformed_name(self): + loader = unittest.TestLoader() + + # XXX Should this raise AttributeError or ValueError? + try: + loader.loadTestsFromName('abc () //', unittest) + except ValueError: + pass + except AttributeError: + pass + else: + self.fail("TestLoader.loadTestsFromName failed to raise ValueError") + + # "The method optionally resolves name relative to the given module" + # + # Does loadTestsFromName raise TypeError when the `module` argument + # isn't a module object? + # + # XXX Accepts the not-a-module object, ignorning the object's type + # This should raise an exception or the method name should be changed + # + # XXX Some people are relying on this, so keep it for now + def test_loadTestsFromName__relative_not_a_module(self): + class MyTestCase(unittest.TestCase): + def test(self): + pass + + class NotAModule(object): + test_2 = MyTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromName('test_2', NotAModule) + + reference = [MyTestCase('test')] + self.assertEqual(list(suite), reference) + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # Does it raise an exception if the name resolves to an invalid + # object? + def test_loadTestsFromName__relative_bad_object(self): + import new + m = new.module('m') + m.testcase_1 = object() + + loader = unittest.TestLoader() + try: + loader.loadTestsFromName('testcase_1', m) + except TypeError: + pass + else: + self.fail("Should have raised TypeError") + + # "The specifier name is a ``dotted name'' that may + # resolve either to ... a test case class" + def test_loadTestsFromName__relative_TestCase_subclass(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + def test(self): + pass + m.testcase_1 = MyTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromName('testcase_1', m) + self.failUnless(isinstance(suite, loader.suiteClass)) + self.assertEqual(list(suite), [MyTestCase('test')]) + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + def test_loadTestsFromName__relative_TestSuite(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + def test(self): + pass + m.testsuite = unittest.TestSuite([MyTestCase('test')]) + + loader = unittest.TestLoader() + suite = loader.loadTestsFromName('testsuite', m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + self.assertEqual(list(suite), [MyTestCase('test')]) + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a test method within a test case class" + def test_loadTestsFromName__relative_testmethod(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + def test(self): + pass + m.testcase_1 = MyTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromName('testcase_1.test', m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + self.assertEqual(list(suite), [MyTestCase('test')]) + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # Does loadTestsFromName() raise the proper exception when trying to + # resolve "a test method within a test case class" that doesn't exist + # for the given name (relative to a provided module)? + def test_loadTestsFromName__relative_invalid_testmethod(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + def test(self): + pass + m.testcase_1 = MyTestCase + + loader = unittest.TestLoader() + try: + loader.loadTestsFromName('testcase_1.testfoo', m) + except AttributeError as e: + self.assertEqual(str(e), "type object 'MyTestCase' has no attribute 'testfoo'") + else: + self.fail("Failed to raise AttributeError") + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a callable object which returns a ... TestSuite instance" + def test_loadTestsFromName__callable__TestSuite(self): + import new + m = new.module('m') + testcase_1 = unittest.FunctionTestCase(lambda: None) + testcase_2 = unittest.FunctionTestCase(lambda: None) + def return_TestSuite(): + return unittest.TestSuite([testcase_1, testcase_2]) + m.return_TestSuite = return_TestSuite + + loader = unittest.TestLoader() + suite = loader.loadTestsFromName('return_TestSuite', m) + self.failUnless(isinstance(suite, loader.suiteClass)) + self.assertEqual(list(suite), [testcase_1, testcase_2]) + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a callable object which returns a TestCase ... instance" + def test_loadTestsFromName__callable__TestCase_instance(self): + import new + m = new.module('m') + testcase_1 = unittest.FunctionTestCase(lambda: None) + def return_TestCase(): + return testcase_1 + m.return_TestCase = return_TestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromName('return_TestCase', m) + self.failUnless(isinstance(suite, loader.suiteClass)) + self.assertEqual(list(suite), [testcase_1]) + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a callable object which returns a TestCase or TestSuite instance" + # + # What happens if the callable returns something else? + def test_loadTestsFromName__callable__wrong_type(self): + import new + m = new.module('m') + def return_wrong(): + return 6 + m.return_wrong = return_wrong + + loader = unittest.TestLoader() + try: + suite = loader.loadTestsFromName('return_wrong', m) + except TypeError: + pass + else: + self.fail("TestLoader.loadTestsFromName failed to raise TypeError") + + # "The specifier can refer to modules and packages which have not been + # imported; they will be imported as a side-effect" + def test_loadTestsFromName__module_not_loaded(self): + # We're going to try to load this module as a side-effect, so it + # better not be loaded before we try. + # + # Why pick audioop? Google shows it isn't used very often, so there's + # a good chance that it won't be imported when this test is run + module_name = 'audioop' + + import sys + if module_name in sys.modules: + del sys.modules[module_name] + + loader = unittest.TestLoader() + try: + suite = loader.loadTestsFromName(module_name) + + self.failUnless(isinstance(suite, loader.suiteClass)) + self.assertEqual(list(suite), []) + + # audioop should now be loaded, thanks to loadTestsFromName() + self.failUnless(module_name in sys.modules) + finally: + del sys.modules[module_name] + + ################################################################ + ### Tests for TestLoader.loadTestsFromName() + + ### Tests for TestLoader.loadTestsFromNames() + ################################################################ + + # "Similar to loadTestsFromName(), but takes a sequence of names rather + # than a single name." + # + # What happens if that sequence of names is empty? + def test_loadTestsFromNames__empty_name_list(self): + loader = unittest.TestLoader() + + suite = loader.loadTestsFromNames([]) + self.failUnless(isinstance(suite, loader.suiteClass)) + self.assertEqual(list(suite), []) + + # "Similar to loadTestsFromName(), but takes a sequence of names rather + # than a single name." + # ... + # "The method optionally resolves name relative to the given module" + # + # What happens if that sequence of names is empty? + # + # XXX Should this raise a ValueError or just return an empty TestSuite? + def test_loadTestsFromNames__relative_empty_name_list(self): + loader = unittest.TestLoader() + + suite = loader.loadTestsFromNames([], unittest) + self.failUnless(isinstance(suite, loader.suiteClass)) + self.assertEqual(list(suite), []) + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # Is ValueError raised in response to an empty name? + def test_loadTestsFromNames__empty_name(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromNames(['']) + except ValueError as e: + self.assertEqual(str(e), "Empty module name") + else: + self.fail("TestLoader.loadTestsFromNames failed to raise ValueError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # What happens when presented with an impossible module name? + def test_loadTestsFromNames__malformed_name(self): + loader = unittest.TestLoader() + + # XXX Should this raise ValueError or ImportError? + try: + loader.loadTestsFromNames(['abc () //']) + except ValueError: + pass + except ImportError: + pass + else: + self.fail("TestLoader.loadTestsFromNames failed to raise ValueError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # What happens when no module can be found for the given name? + def test_loadTestsFromNames__unknown_module_name(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromNames(['sdasfasfasdf']) + except ImportError as e: + self.assertEqual(str(e), "No module named sdasfasfasdf") + else: + self.fail("TestLoader.loadTestsFromNames failed to raise ImportError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # What happens when the module can be found, but not the attribute? + def test_loadTestsFromNames__unknown_attr_name(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromNames(['unittest.sdasfasfasdf', 'unittest']) + except AttributeError as e: + self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") + else: + self.fail("TestLoader.loadTestsFromNames failed to raise AttributeError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # ... + # "The method optionally resolves name relative to the given module" + # + # What happens when given an unknown attribute on a specified `module` + # argument? + def test_loadTestsFromNames__unknown_name_relative_1(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromNames(['sdasfasfasdf'], unittest) + except AttributeError as e: + self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") + else: + self.fail("TestLoader.loadTestsFromName failed to raise AttributeError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # ... + # "The method optionally resolves name relative to the given module" + # + # Do unknown attributes (relative to a provided module) still raise an + # exception even in the presence of valid attribute names? + def test_loadTestsFromNames__unknown_name_relative_2(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromNames(['TestCase', 'sdasfasfasdf'], unittest) + except AttributeError as e: + self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") + else: + self.fail("TestLoader.loadTestsFromName failed to raise AttributeError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # ... + # "The method optionally resolves name relative to the given module" + # + # What happens when faced with the empty string? + # + # XXX This currently raises AttributeError, though ValueError is probably + # more appropriate + def test_loadTestsFromNames__relative_empty_name(self): + loader = unittest.TestLoader() + + try: + loader.loadTestsFromNames([''], unittest) + except AttributeError: + pass + else: + self.fail("Failed to raise ValueError") + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # ... + # "The method optionally resolves name relative to the given module" + # + # What happens when presented with an impossible attribute name? + def test_loadTestsFromNames__relative_malformed_name(self): + loader = unittest.TestLoader() + + # XXX Should this raise AttributeError or ValueError? + try: + loader.loadTestsFromNames(['abc () //'], unittest) + except AttributeError: + pass + except ValueError: + pass + else: + self.fail("TestLoader.loadTestsFromNames failed to raise ValueError") + + # "The method optionally resolves name relative to the given module" + # + # Does loadTestsFromNames() make sure the provided `module` is in fact + # a module? + # + # XXX This validation is currently not done. This flexibility should + # either be documented or a TypeError should be raised. + def test_loadTestsFromNames__relative_not_a_module(self): + class MyTestCase(unittest.TestCase): + def test(self): + pass + + class NotAModule(object): + test_2 = MyTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromNames(['test_2'], NotAModule) + + reference = [unittest.TestSuite([MyTestCase('test')])] + self.assertEqual(list(suite), reference) + + # "The specifier name is a ``dotted name'' that may resolve either to + # a module, a test case class, a TestSuite instance, a test method + # within a test case class, or a callable object which returns a + # TestCase or TestSuite instance." + # + # Does it raise an exception if the name resolves to an invalid + # object? + def test_loadTestsFromNames__relative_bad_object(self): + import new + m = new.module('m') + m.testcase_1 = object() + + loader = unittest.TestLoader() + try: + loader.loadTestsFromNames(['testcase_1'], m) + except TypeError: + pass + else: + self.fail("Should have raised TypeError") + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a test case class" + def test_loadTestsFromNames__relative_TestCase_subclass(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + def test(self): + pass + m.testcase_1 = MyTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromNames(['testcase_1'], m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + expected = loader.suiteClass([MyTestCase('test')]) + self.assertEqual(list(suite), [expected]) + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a TestSuite instance" + def test_loadTestsFromNames__relative_TestSuite(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + def test(self): + pass + m.testsuite = unittest.TestSuite([MyTestCase('test')]) + + loader = unittest.TestLoader() + suite = loader.loadTestsFromNames(['testsuite'], m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + self.assertEqual(list(suite), [m.testsuite]) + + # "The specifier name is a ``dotted name'' that may resolve ... to ... a + # test method within a test case class" + def test_loadTestsFromNames__relative_testmethod(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + def test(self): + pass + m.testcase_1 = MyTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromNames(['testcase_1.test'], m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + ref_suite = unittest.TestSuite([MyTestCase('test')]) + self.assertEqual(list(suite), [ref_suite]) + + # "The specifier name is a ``dotted name'' that may resolve ... to ... a + # test method within a test case class" + # + # Does the method gracefully handle names that initially look like they + # resolve to "a test method within a test case class" but don't? + def test_loadTestsFromNames__relative_invalid_testmethod(self): + import new + m = new.module('m') + class MyTestCase(unittest.TestCase): + def test(self): + pass + m.testcase_1 = MyTestCase + + loader = unittest.TestLoader() + try: + loader.loadTestsFromNames(['testcase_1.testfoo'], m) + except AttributeError as e: + self.assertEqual(str(e), "type object 'MyTestCase' has no attribute 'testfoo'") + else: + self.fail("Failed to raise AttributeError") + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a callable object which returns a ... TestSuite instance" + def test_loadTestsFromNames__callable__TestSuite(self): + import new + m = new.module('m') + testcase_1 = unittest.FunctionTestCase(lambda: None) + testcase_2 = unittest.FunctionTestCase(lambda: None) + def return_TestSuite(): + return unittest.TestSuite([testcase_1, testcase_2]) + m.return_TestSuite = return_TestSuite + + loader = unittest.TestLoader() + suite = loader.loadTestsFromNames(['return_TestSuite'], m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + expected = unittest.TestSuite([testcase_1, testcase_2]) + self.assertEqual(list(suite), [expected]) + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a callable object which returns a TestCase ... instance" + def test_loadTestsFromNames__callable__TestCase_instance(self): + import new + m = new.module('m') + testcase_1 = unittest.FunctionTestCase(lambda: None) + def return_TestCase(): + return testcase_1 + m.return_TestCase = return_TestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromNames(['return_TestCase'], m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + ref_suite = unittest.TestSuite([testcase_1]) + self.assertEqual(list(suite), [ref_suite]) + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a callable object which returns a TestCase or TestSuite instance" + # + # Are staticmethods handled correctly? + def test_loadTestsFromNames__callable__call_staticmethod(self): + import new + m = new.module('m') + class Test1(unittest.TestCase): + def test(self): + pass + + testcase_1 = Test1('test') + class Foo(unittest.TestCase): + @staticmethod + def foo(): + return testcase_1 + m.Foo = Foo + + loader = unittest.TestLoader() + suite = loader.loadTestsFromNames(['Foo.foo'], m) + self.failUnless(isinstance(suite, loader.suiteClass)) + + ref_suite = unittest.TestSuite([testcase_1]) + self.assertEqual(list(suite), [ref_suite]) + + # "The specifier name is a ``dotted name'' that may resolve ... to + # ... a callable object which returns a TestCase or TestSuite instance" + # + # What happens when the callable returns something else? + def test_loadTestsFromNames__callable__wrong_type(self): + import new + m = new.module('m') + def return_wrong(): + return 6 + m.return_wrong = return_wrong + + loader = unittest.TestLoader() + try: + suite = loader.loadTestsFromNames(['return_wrong'], m) + except TypeError: + pass + else: + self.fail("TestLoader.loadTestsFromNames failed to raise TypeError") + + # "The specifier can refer to modules and packages which have not been + # imported; they will be imported as a side-effect" + def test_loadTestsFromNames__module_not_loaded(self): + # We're going to try to load this module as a side-effect, so it + # better not be loaded before we try. + # + # Why pick audioop? Google shows it isn't used very often, so there's + # a good chance that it won't be imported when this test is run + module_name = 'audioop' + + import sys + if module_name in sys.modules: + del sys.modules[module_name] + + loader = unittest.TestLoader() + try: + suite = loader.loadTestsFromNames([module_name]) + + self.failUnless(isinstance(suite, loader.suiteClass)) + self.assertEqual(list(suite), [unittest.TestSuite()]) + + # audioop should now be loaded, thanks to loadTestsFromName() + self.failUnless(module_name in sys.modules) + finally: + del sys.modules[module_name] + + ################################################################ + ### /Tests for TestLoader.loadTestsFromNames() + + ### Tests for TestLoader.getTestCaseNames() + ################################################################ + + # "Return a sorted sequence of method names found within testCaseClass" + # + # Test.foobar is defined to make sure getTestCaseNames() respects + # loader.testMethodPrefix + def test_getTestCaseNames(self): + class Test(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foobar(self): pass + + loader = unittest.TestLoader() + + self.assertEqual(loader.getTestCaseNames(Test), ['test_1', 'test_2']) + + # "Return a sorted sequence of method names found within testCaseClass" + # + # Does getTestCaseNames() behave appropriately if no tests are found? + def test_getTestCaseNames__no_tests(self): + class Test(unittest.TestCase): + def foobar(self): pass + + loader = unittest.TestLoader() + + self.assertEqual(loader.getTestCaseNames(Test), []) + + # "Return a sorted sequence of method names found within testCaseClass" + # + # Are not-TestCases handled gracefully? + # + # XXX This should raise a TypeError, not return a list + # + # XXX It's too late in the 2.5 release cycle to fix this, but it should + # probably be revisited for 2.6 + def test_getTestCaseNames__not_a_TestCase(self): + class BadCase(int): + def test_foo(self): + pass + + loader = unittest.TestLoader() + names = loader.getTestCaseNames(BadCase) + + self.assertEqual(names, ['test_foo']) + + # "Return a sorted sequence of method names found within testCaseClass" + # + # Make sure inherited names are handled. + # + # TestP.foobar is defined to make sure getTestCaseNames() respects + # loader.testMethodPrefix + def test_getTestCaseNames__inheritance(self): + class TestP(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foobar(self): pass + + class TestC(TestP): + def test_1(self): pass + def test_3(self): pass + + loader = unittest.TestLoader() + + names = ['test_1', 'test_2', 'test_3'] + self.assertEqual(loader.getTestCaseNames(TestC), names) + + ################################################################ + ### /Tests for TestLoader.getTestCaseNames() + + ### Tests for TestLoader.testMethodPrefix + ################################################################ + + # "String giving the prefix of method names which will be interpreted as + # test methods" + # + # Implicit in the documentation is that testMethodPrefix is respected by + # all loadTestsFrom* methods. + def test_testMethodPrefix__loadTestsFromTestCase(self): + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foo_bar(self): pass + + tests_1 = unittest.TestSuite([Foo('foo_bar')]) + tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')]) + + loader = unittest.TestLoader() + loader.testMethodPrefix = 'foo' + self.assertEqual(loader.loadTestsFromTestCase(Foo), tests_1) + + loader.testMethodPrefix = 'test' + self.assertEqual(loader.loadTestsFromTestCase(Foo), tests_2) + + # "String giving the prefix of method names which will be interpreted as + # test methods" + # + # Implicit in the documentation is that testMethodPrefix is respected by + # all loadTestsFrom* methods. + def test_testMethodPrefix__loadTestsFromModule(self): + import new + m = new.module('m') + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foo_bar(self): pass + m.Foo = Foo + + tests_1 = [unittest.TestSuite([Foo('foo_bar')])] + tests_2 = [unittest.TestSuite([Foo('test_1'), Foo('test_2')])] + + loader = unittest.TestLoader() + loader.testMethodPrefix = 'foo' + self.assertEqual(list(loader.loadTestsFromModule(m)), tests_1) + + loader.testMethodPrefix = 'test' + self.assertEqual(list(loader.loadTestsFromModule(m)), tests_2) + + # "String giving the prefix of method names which will be interpreted as + # test methods" + # + # Implicit in the documentation is that testMethodPrefix is respected by + # all loadTestsFrom* methods. + def test_testMethodPrefix__loadTestsFromName(self): + import new + m = new.module('m') + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foo_bar(self): pass + m.Foo = Foo + + tests_1 = unittest.TestSuite([Foo('foo_bar')]) + tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')]) + + loader = unittest.TestLoader() + loader.testMethodPrefix = 'foo' + self.assertEqual(loader.loadTestsFromName('Foo', m), tests_1) + + loader.testMethodPrefix = 'test' + self.assertEqual(loader.loadTestsFromName('Foo', m), tests_2) + + # "String giving the prefix of method names which will be interpreted as + # test methods" + # + # Implicit in the documentation is that testMethodPrefix is respected by + # all loadTestsFrom* methods. + def test_testMethodPrefix__loadTestsFromNames(self): + import new + m = new.module('m') + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foo_bar(self): pass + m.Foo = Foo + + tests_1 = unittest.TestSuite([unittest.TestSuite([Foo('foo_bar')])]) + tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')]) + tests_2 = unittest.TestSuite([tests_2]) + + loader = unittest.TestLoader() + loader.testMethodPrefix = 'foo' + self.assertEqual(loader.loadTestsFromNames(['Foo'], m), tests_1) + + loader.testMethodPrefix = 'test' + self.assertEqual(loader.loadTestsFromNames(['Foo'], m), tests_2) + + # "The default value is 'test'" + def test_testMethodPrefix__default_value(self): + loader = unittest.TestLoader() + self.failUnless(loader.testMethodPrefix == 'test') + + ################################################################ + ### /Tests for TestLoader.testMethodPrefix + + ### Tests for TestLoader.sortTestMethodsUsing + ################################################################ + + # "Function to be used to compare method names when sorting them in + # getTestCaseNames() and all the loadTestsFromX() methods" + def test_sortTestMethodsUsing__loadTestsFromTestCase(self): + def reversed_cmp(x, y): + return -cmp(x, y) + + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + + loader = unittest.TestLoader() + loader.sortTestMethodsUsing = reversed_cmp + + tests = loader.suiteClass([Foo('test_2'), Foo('test_1')]) + self.assertEqual(loader.loadTestsFromTestCase(Foo), tests) + + # "Function to be used to compare method names when sorting them in + # getTestCaseNames() and all the loadTestsFromX() methods" + def test_sortTestMethodsUsing__loadTestsFromModule(self): + def reversed_cmp(x, y): + return -cmp(x, y) + + import new + m = new.module('m') + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + m.Foo = Foo + + loader = unittest.TestLoader() + loader.sortTestMethodsUsing = reversed_cmp + + tests = [loader.suiteClass([Foo('test_2'), Foo('test_1')])] + self.assertEqual(list(loader.loadTestsFromModule(m)), tests) + + # "Function to be used to compare method names when sorting them in + # getTestCaseNames() and all the loadTestsFromX() methods" + def test_sortTestMethodsUsing__loadTestsFromName(self): + def reversed_cmp(x, y): + return -cmp(x, y) + + import new + m = new.module('m') + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + m.Foo = Foo + + loader = unittest.TestLoader() + loader.sortTestMethodsUsing = reversed_cmp + + tests = loader.suiteClass([Foo('test_2'), Foo('test_1')]) + self.assertEqual(loader.loadTestsFromName('Foo', m), tests) + + # "Function to be used to compare method names when sorting them in + # getTestCaseNames() and all the loadTestsFromX() methods" + def test_sortTestMethodsUsing__loadTestsFromNames(self): + def reversed_cmp(x, y): + return -cmp(x, y) + + import new + m = new.module('m') + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + m.Foo = Foo + + loader = unittest.TestLoader() + loader.sortTestMethodsUsing = reversed_cmp + + tests = [loader.suiteClass([Foo('test_2'), Foo('test_1')])] + self.assertEqual(list(loader.loadTestsFromNames(['Foo'], m)), tests) + + # "Function to be used to compare method names when sorting them in + # getTestCaseNames()" + # + # Does it actually affect getTestCaseNames()? + def test_sortTestMethodsUsing__getTestCaseNames(self): + def reversed_cmp(x, y): + return -cmp(x, y) + + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + + loader = unittest.TestLoader() + loader.sortTestMethodsUsing = reversed_cmp + + test_names = ['test_2', 'test_1'] + self.assertEqual(loader.getTestCaseNames(Foo), test_names) + + # "The default value is the built-in cmp() function" + def test_sortTestMethodsUsing__default_value(self): + loader = unittest.TestLoader() + self.failUnless(loader.sortTestMethodsUsing is cmp) + + # "it can be set to None to disable the sort." + # + # XXX How is this different from reassigning cmp? Are the tests returned + # in a random order or something? This behaviour should die + def test_sortTestMethodsUsing__None(self): + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + + loader = unittest.TestLoader() + loader.sortTestMethodsUsing = None + + test_names = ['test_2', 'test_1'] + self.assertEqual(set(loader.getTestCaseNames(Foo)), set(test_names)) + + ################################################################ + ### /Tests for TestLoader.sortTestMethodsUsing + + ### Tests for TestLoader.suiteClass + ################################################################ + + # "Callable object that constructs a test suite from a list of tests." + def test_suiteClass__loadTestsFromTestCase(self): + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foo_bar(self): pass + + tests = [Foo('test_1'), Foo('test_2')] + + loader = unittest.TestLoader() + loader.suiteClass = list + self.assertEqual(loader.loadTestsFromTestCase(Foo), tests) + + # It is implicit in the documentation for TestLoader.suiteClass that + # all TestLoader.loadTestsFrom* methods respect it. Let's make sure + def test_suiteClass__loadTestsFromModule(self): + import new + m = new.module('m') + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foo_bar(self): pass + m.Foo = Foo + + tests = [[Foo('test_1'), Foo('test_2')]] + + loader = unittest.TestLoader() + loader.suiteClass = list + self.assertEqual(loader.loadTestsFromModule(m), tests) + + # It is implicit in the documentation for TestLoader.suiteClass that + # all TestLoader.loadTestsFrom* methods respect it. Let's make sure + def test_suiteClass__loadTestsFromName(self): + import new + m = new.module('m') + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foo_bar(self): pass + m.Foo = Foo + + tests = [Foo('test_1'), Foo('test_2')] + + loader = unittest.TestLoader() + loader.suiteClass = list + self.assertEqual(loader.loadTestsFromName('Foo', m), tests) + + # It is implicit in the documentation for TestLoader.suiteClass that + # all TestLoader.loadTestsFrom* methods respect it. Let's make sure + def test_suiteClass__loadTestsFromNames(self): + import new + m = new.module('m') + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def foo_bar(self): pass + m.Foo = Foo + + tests = [[Foo('test_1'), Foo('test_2')]] + + loader = unittest.TestLoader() + loader.suiteClass = list + self.assertEqual(loader.loadTestsFromNames(['Foo'], m), tests) + + # "The default value is the TestSuite class" + def test_suiteClass__default_value(self): + loader = unittest.TestLoader() + self.failUnless(loader.suiteClass is unittest.TestSuite) + + ################################################################ + ### /Tests for TestLoader.suiteClass + +### Support code for Test_TestSuite +################################################################ + +class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + def test_3(self): pass + def runTest(self): pass + +def _mk_TestSuite(*names): + return unittest.TestSuite(Foo(n) for n in names) + +################################################################ +### /Support code for Test_TestSuite + +class Test_TestSuite(TestCase, TestEquality): + + ### Set up attributes needed by inherited tests + ################################################################ + + # Used by TestEquality.test_eq + eq_pairs = [(unittest.TestSuite(), unittest.TestSuite()) + ,(unittest.TestSuite(), unittest.TestSuite([])) + ,(_mk_TestSuite('test_1'), _mk_TestSuite('test_1'))] + + # Used by TestEquality.test_ne + ne_pairs = [(unittest.TestSuite(), _mk_TestSuite('test_1')) + ,(unittest.TestSuite([]), _mk_TestSuite('test_1')) + ,(_mk_TestSuite('test_1', 'test_2'), _mk_TestSuite('test_1', 'test_3')) + ,(_mk_TestSuite('test_1'), _mk_TestSuite('test_2'))] + + ################################################################ + ### /Set up attributes needed by inherited tests + + ### Tests for TestSuite.__init__ + ################################################################ + + # "class TestSuite([tests])" + # + # The tests iterable should be optional + def test_init__tests_optional(self): + suite = unittest.TestSuite() + + self.assertEqual(suite.countTestCases(), 0) + + # "class TestSuite([tests])" + # ... + # "If tests is given, it must be an iterable of individual test cases + # or other test suites that will be used to build the suite initially" + # + # TestSuite should deal with empty tests iterables by allowing the + # creation of an empty suite + def test_init__empty_tests(self): + suite = unittest.TestSuite([]) + + self.assertEqual(suite.countTestCases(), 0) + + # "class TestSuite([tests])" + # ... + # "If tests is given, it must be an iterable of individual test cases + # or other test suites that will be used to build the suite initially" + # + # TestSuite should allow any iterable to provide tests + def test_init__tests_from_any_iterable(self): + def tests(): + yield unittest.FunctionTestCase(lambda: None) + yield unittest.FunctionTestCase(lambda: None) + + suite_1 = unittest.TestSuite(tests()) + self.assertEqual(suite_1.countTestCases(), 2) + + suite_2 = unittest.TestSuite(suite_1) + self.assertEqual(suite_2.countTestCases(), 2) + + suite_3 = unittest.TestSuite(set(suite_1)) + self.assertEqual(suite_3.countTestCases(), 2) + + # "class TestSuite([tests])" + # ... + # "If tests is given, it must be an iterable of individual test cases + # or other test suites that will be used to build the suite initially" + # + # Does TestSuite() also allow other TestSuite() instances to be present + # in the tests iterable? + def test_init__TestSuite_instances_in_tests(self): + def tests(): + ftc = unittest.FunctionTestCase(lambda: None) + yield unittest.TestSuite([ftc]) + yield unittest.FunctionTestCase(lambda: None) + + suite = unittest.TestSuite(tests()) + self.assertEqual(suite.countTestCases(), 2) + + ################################################################ + ### /Tests for TestSuite.__init__ + + # Container types should support the iter protocol + def test_iter(self): + test1 = unittest.FunctionTestCase(lambda: None) + test2 = unittest.FunctionTestCase(lambda: None) + suite = unittest.TestSuite((test1, test2)) + + self.assertEqual(list(suite), [test1, test2]) + + # "Return the number of tests represented by the this test object. + # ...this method is also implemented by the TestSuite class, which can + # return larger [greater than 1] values" + # + # Presumably an empty TestSuite returns 0? + def test_countTestCases_zero_simple(self): + suite = unittest.TestSuite() + + self.assertEqual(suite.countTestCases(), 0) + + # "Return the number of tests represented by the this test object. + # ...this method is also implemented by the TestSuite class, which can + # return larger [greater than 1] values" + # + # Presumably an empty TestSuite (even if it contains other empty + # TestSuite instances) returns 0? + def test_countTestCases_zero_nested(self): + class Test1(unittest.TestCase): + def test(self): + pass + + suite = unittest.TestSuite([unittest.TestSuite()]) + + self.assertEqual(suite.countTestCases(), 0) + + # "Return the number of tests represented by the this test object. + # ...this method is also implemented by the TestSuite class, which can + # return larger [greater than 1] values" + def test_countTestCases_simple(self): + test1 = unittest.FunctionTestCase(lambda: None) + test2 = unittest.FunctionTestCase(lambda: None) + suite = unittest.TestSuite((test1, test2)) + + self.assertEqual(suite.countTestCases(), 2) + + # "Return the number of tests represented by the this test object. + # ...this method is also implemented by the TestSuite class, which can + # return larger [greater than 1] values" + # + # Make sure this holds for nested TestSuite instances, too + def test_countTestCases_nested(self): + class Test1(unittest.TestCase): + def test1(self): pass + def test2(self): pass + + test2 = unittest.FunctionTestCase(lambda: None) + test3 = unittest.FunctionTestCase(lambda: None) + child = unittest.TestSuite((Test1('test2'), test2)) + parent = unittest.TestSuite((test3, child, Test1('test1'))) + + self.assertEqual(parent.countTestCases(), 4) + + # "Run the tests associated with this suite, collecting the result into + # the test result object passed as result." + # + # And if there are no tests? What then? + def test_run__empty_suite(self): + events = [] + result = LoggingResult(events) + + suite = unittest.TestSuite() + + suite.run(result) + + self.assertEqual(events, []) + + # "Note that unlike TestCase.run(), TestSuite.run() requires the + # "result object to be passed in." + def test_run__requires_result(self): + suite = unittest.TestSuite() + + try: + suite.run() + except TypeError: + pass + else: + self.fail("Failed to raise TypeError") + + # "Run the tests associated with this suite, collecting the result into + # the test result object passed as result." + def test_run(self): + events = [] + result = LoggingResult(events) + + class LoggingCase(unittest.TestCase): + def run(self, result): + events.append('run %s' % self._testMethodName) + + def test1(self): pass + def test2(self): pass + + tests = [LoggingCase('test1'), LoggingCase('test2')] + + unittest.TestSuite(tests).run(result) + + self.assertEqual(events, ['run test1', 'run test2']) + + # "Add a TestCase ... to the suite" + def test_addTest__TestCase(self): + class Foo(unittest.TestCase): + def test(self): pass + + test = Foo('test') + suite = unittest.TestSuite() + + suite.addTest(test) + + self.assertEqual(suite.countTestCases(), 1) + self.assertEqual(list(suite), [test]) + + # "Add a ... TestSuite to the suite" + def test_addTest__TestSuite(self): + class Foo(unittest.TestCase): + def test(self): pass + + suite_2 = unittest.TestSuite([Foo('test')]) + + suite = unittest.TestSuite() + suite.addTest(suite_2) + + self.assertEqual(suite.countTestCases(), 1) + self.assertEqual(list(suite), [suite_2]) + + # "Add all the tests from an iterable of TestCase and TestSuite + # instances to this test suite." + # + # "This is equivalent to iterating over tests, calling addTest() for + # each element" + def test_addTests(self): + class Foo(unittest.TestCase): + def test_1(self): pass + def test_2(self): pass + + test_1 = Foo('test_1') + test_2 = Foo('test_2') + inner_suite = unittest.TestSuite([test_2]) + + def gen(): + yield test_1 + yield test_2 + yield inner_suite + + suite_1 = unittest.TestSuite() + suite_1.addTests(gen()) + + self.assertEqual(list(suite_1), list(gen())) + + # "This is equivalent to iterating over tests, calling addTest() for + # each element" + suite_2 = unittest.TestSuite() + for t in gen(): + suite_2.addTest(t) + + self.assertEqual(suite_1, suite_2) + + # "Add all the tests from an iterable of TestCase and TestSuite + # instances to this test suite." + # + # What happens if it doesn't get an iterable? + def test_addTest__noniterable(self): + suite = unittest.TestSuite() + + try: + suite.addTests(5) + except TypeError: + pass + else: + self.fail("Failed to raise TypeError") + + def test_addTest__noncallable(self): + suite = unittest.TestSuite() + self.assertRaises(TypeError, suite.addTest, 5) + + def test_addTest__casesuiteclass(self): + suite = unittest.TestSuite() + self.assertRaises(TypeError, suite.addTest, Test_TestSuite) + self.assertRaises(TypeError, suite.addTest, unittest.TestSuite) + + def test_addTests__string(self): + suite = unittest.TestSuite() + self.assertRaises(TypeError, suite.addTests, "foo") + + +class Test_FunctionTestCase(TestCase): + + # "Return the number of tests represented by the this test object. For + # TestCase instances, this will always be 1" + def test_countTestCases(self): + test = unittest.FunctionTestCase(lambda: None) + + self.assertEqual(test.countTestCases(), 1) + + # "When a setUp() method is defined, the test runner will run that method + # prior to each test. Likewise, if a tearDown() method is defined, the + # test runner will invoke that method after each test. In the example, + # setUp() was used to create a fresh sequence for each test." + # + # Make sure the proper call order is maintained, even if setUp() raises + # an exception. + def test_run_call_order__error_in_setUp(self): + events = [] + result = LoggingResult(events) + + def setUp(): + events.append('setUp') + raise RuntimeError('raised by setUp') + + def test(): + events.append('test') + + def tearDown(): + events.append('tearDown') + + expected = ['startTest', 'setUp', 'addError', 'stopTest'] + unittest.FunctionTestCase(test, setUp, tearDown).run(result) + self.assertEqual(events, expected) + + # "When a setUp() method is defined, the test runner will run that method + # prior to each test. Likewise, if a tearDown() method is defined, the + # test runner will invoke that method after each test. In the example, + # setUp() was used to create a fresh sequence for each test." + # + # Make sure the proper call order is maintained, even if the test raises + # an error (as opposed to a failure). + def test_run_call_order__error_in_test(self): + events = [] + result = LoggingResult(events) + + def setUp(): + events.append('setUp') + + def test(): + events.append('test') + raise RuntimeError('raised by test') + + def tearDown(): + events.append('tearDown') + + expected = ['startTest', 'setUp', 'test', 'addError', 'tearDown', + 'stopTest'] + unittest.FunctionTestCase(test, setUp, tearDown).run(result) + self.assertEqual(events, expected) + + # "When a setUp() method is defined, the test runner will run that method + # prior to each test. Likewise, if a tearDown() method is defined, the + # test runner will invoke that method after each test. In the example, + # setUp() was used to create a fresh sequence for each test." + # + # Make sure the proper call order is maintained, even if the test signals + # a failure (as opposed to an error). + def test_run_call_order__failure_in_test(self): + events = [] + result = LoggingResult(events) + + def setUp(): + events.append('setUp') + + def test(): + events.append('test') + self.fail('raised by test') + + def tearDown(): + events.append('tearDown') + + expected = ['startTest', 'setUp', 'test', 'addFailure', 'tearDown', + 'stopTest'] + unittest.FunctionTestCase(test, setUp, tearDown).run(result) + self.assertEqual(events, expected) + + # "When a setUp() method is defined, the test runner will run that method + # prior to each test. Likewise, if a tearDown() method is defined, the + # test runner will invoke that method after each test. In the example, + # setUp() was used to create a fresh sequence for each test." + # + # Make sure the proper call order is maintained, even if tearDown() raises + # an exception. + def test_run_call_order__error_in_tearDown(self): + events = [] + result = LoggingResult(events) + + def setUp(): + events.append('setUp') + + def test(): + events.append('test') + + def tearDown(): + events.append('tearDown') + raise RuntimeError('raised by tearDown') + + expected = ['startTest', 'setUp', 'test', 'tearDown', 'addError', + 'stopTest'] + unittest.FunctionTestCase(test, setUp, tearDown).run(result) + self.assertEqual(events, expected) + + # "Return a string identifying the specific test case." + # + # Because of the vague nature of the docs, I'm not going to lock this + # test down too much. Really all that can be asserted is that the id() + # will be a string (either 8-byte or unicode -- again, because the docs + # just say "string") + def test_id(self): + test = unittest.FunctionTestCase(lambda: None) + + self.failUnless(isinstance(test.id(), basestring)) + + # "Returns a one-line description of the test, or None if no description + # has been provided. The default implementation of this method returns + # the first line of the test method's docstring, if available, or None." + def test_shortDescription__no_docstring(self): + test = unittest.FunctionTestCase(lambda: None) + + self.assertEqual(test.shortDescription(), None) + + # "Returns a one-line description of the test, or None if no description + # has been provided. The default implementation of this method returns + # the first line of the test method's docstring, if available, or None." + def test_shortDescription__singleline_docstring(self): + desc = "this tests foo" + test = unittest.FunctionTestCase(lambda: None, description=desc) + + self.assertEqual(test.shortDescription(), "this tests foo") + +class Test_TestResult(TestCase): + # Note: there are not separate tests for TestResult.wasSuccessful(), + # TestResult.errors, TestResult.failures, TestResult.testsRun or + # TestResult.shouldStop because these only have meaning in terms of + # other TestResult methods. + # + # Accordingly, tests for the aforenamed attributes are incorporated + # in with the tests for the defining methods. + ################################################################ + + def test_init(self): + result = unittest.TestResult() + + self.failUnless(result.wasSuccessful()) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.failures), 0) + self.assertEqual(result.testsRun, 0) + self.assertEqual(result.shouldStop, False) + + # "This method can be called to signal that the set of tests being + # run should be aborted by setting the TestResult's shouldStop + # attribute to True." + def test_stop(self): + result = unittest.TestResult() + + result.stop() + + self.assertEqual(result.shouldStop, True) + + # "Called when the test case test is about to be run. The default + # implementation simply increments the instance's testsRun counter." + def test_startTest(self): + class Foo(unittest.TestCase): + def test_1(self): + pass + + test = Foo('test_1') + + result = unittest.TestResult() + + result.startTest(test) + + self.failUnless(result.wasSuccessful()) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.failures), 0) + self.assertEqual(result.testsRun, 1) + self.assertEqual(result.shouldStop, False) + + result.stopTest(test) + + # "Called after the test case test has been executed, regardless of + # the outcome. The default implementation does nothing." + def test_stopTest(self): + class Foo(unittest.TestCase): + def test_1(self): + pass + + test = Foo('test_1') + + result = unittest.TestResult() + + result.startTest(test) + + self.failUnless(result.wasSuccessful()) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.failures), 0) + self.assertEqual(result.testsRun, 1) + self.assertEqual(result.shouldStop, False) + + result.stopTest(test) + + # Same tests as above; make sure nothing has changed + self.failUnless(result.wasSuccessful()) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.failures), 0) + self.assertEqual(result.testsRun, 1) + self.assertEqual(result.shouldStop, False) + + # "addSuccess(test)" + # ... + # "Called when the test case test succeeds" + # ... + # "wasSuccessful() - Returns True if all tests run so far have passed, + # otherwise returns False" + # ... + # "testsRun - The total number of tests run so far." + # ... + # "errors - A list containing 2-tuples of TestCase instances and + # formatted tracebacks. Each tuple represents a test which raised an + # unexpected exception. Contains formatted + # tracebacks instead of sys.exc_info() results." + # ... + # "failures - A list containing 2-tuples of TestCase instances and + # formatted tracebacks. Each tuple represents a test where a failure was + # explicitly signalled using the TestCase.fail*() or TestCase.assert*() + # methods. Contains formatted tracebacks instead + # of sys.exc_info() results." + def test_addSuccess(self): + class Foo(unittest.TestCase): + def test_1(self): + pass + + test = Foo('test_1') + + result = unittest.TestResult() + + result.startTest(test) + result.addSuccess(test) + result.stopTest(test) + + self.failUnless(result.wasSuccessful()) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.failures), 0) + self.assertEqual(result.testsRun, 1) + self.assertEqual(result.shouldStop, False) + + # "addFailure(test, err)" + # ... + # "Called when the test case test signals a failure. err is a tuple of + # the form returned by sys.exc_info(): (type, value, traceback)" + # ... + # "wasSuccessful() - Returns True if all tests run so far have passed, + # otherwise returns False" + # ... + # "testsRun - The total number of tests run so far." + # ... + # "errors - A list containing 2-tuples of TestCase instances and + # formatted tracebacks. Each tuple represents a test which raised an + # unexpected exception. Contains formatted + # tracebacks instead of sys.exc_info() results." + # ... + # "failures - A list containing 2-tuples of TestCase instances and + # formatted tracebacks. Each tuple represents a test where a failure was + # explicitly signalled using the TestCase.fail*() or TestCase.assert*() + # methods. Contains formatted tracebacks instead + # of sys.exc_info() results." + def test_addFailure(self): + import sys + + class Foo(unittest.TestCase): + def test_1(self): + pass + + test = Foo('test_1') + try: + test.fail("foo") + except: + exc_info_tuple = sys.exc_info() + + result = unittest.TestResult() + + result.startTest(test) + result.addFailure(test, exc_info_tuple) + result.stopTest(test) + + self.failIf(result.wasSuccessful()) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.failures), 1) + self.assertEqual(result.testsRun, 1) + self.assertEqual(result.shouldStop, False) + + test_case, formatted_exc = result.failures[0] + self.failUnless(test_case is test) + self.failUnless(isinstance(formatted_exc, str)) + + # "addError(test, err)" + # ... + # "Called when the test case test raises an unexpected exception err + # is a tuple of the form returned by sys.exc_info(): + # (type, value, traceback)" + # ... + # "wasSuccessful() - Returns True if all tests run so far have passed, + # otherwise returns False" + # ... + # "testsRun - The total number of tests run so far." + # ... + # "errors - A list containing 2-tuples of TestCase instances and + # formatted tracebacks. Each tuple represents a test which raised an + # unexpected exception. Contains formatted + # tracebacks instead of sys.exc_info() results." + # ... + # "failures - A list containing 2-tuples of TestCase instances and + # formatted tracebacks. Each tuple represents a test where a failure was + # explicitly signalled using the TestCase.fail*() or TestCase.assert*() + # methods. Contains formatted tracebacks instead + # of sys.exc_info() results." + def test_addError(self): + import sys + + class Foo(unittest.TestCase): + def test_1(self): + pass + + test = Foo('test_1') + try: + raise TypeError() + except: + exc_info_tuple = sys.exc_info() + + result = unittest.TestResult() + + result.startTest(test) + result.addError(test, exc_info_tuple) + result.stopTest(test) + + self.failIf(result.wasSuccessful()) + self.assertEqual(len(result.errors), 1) + self.assertEqual(len(result.failures), 0) + self.assertEqual(result.testsRun, 1) + self.assertEqual(result.shouldStop, False) + + test_case, formatted_exc = result.errors[0] + self.failUnless(test_case is test) + self.failUnless(isinstance(formatted_exc, str)) + +### Support code for Test_TestCase +################################################################ + +class Foo(unittest.TestCase): + def runTest(self): pass + def test1(self): pass + +class Bar(Foo): + def test2(self): pass + +################################################################ +### /Support code for Test_TestCase + +class Test_TestCase(TestCase, TestEquality, TestHashing): + + ### Set up attributes used by inherited tests + ################################################################ + + # Used by TestHashing.test_hash and TestEquality.test_eq + eq_pairs = [(Foo('test1'), Foo('test1'))] + + # Used by TestEquality.test_ne + ne_pairs = [(Foo('test1'), Foo('runTest')) + ,(Foo('test1'), Bar('test1')) + ,(Foo('test1'), Bar('test2'))] + + ################################################################ + ### /Set up attributes used by inherited tests + + + # "class TestCase([methodName])" + # ... + # "Each instance of TestCase will run a single test method: the + # method named methodName." + # ... + # "methodName defaults to "runTest"." + # + # Make sure it really is optional, and that it defaults to the proper + # thing. + def test_init__no_test_name(self): + class Test(unittest.TestCase): + def runTest(self): raise MyException() + def test(self): pass + + self.assertEqual(Test().id()[-13:], '.Test.runTest') + + # "class TestCase([methodName])" + # ... + # "Each instance of TestCase will run a single test method: the + # method named methodName." + def test_init__test_name__valid(self): + class Test(unittest.TestCase): + def runTest(self): raise MyException() + def test(self): pass + + self.assertEqual(Test('test').id()[-10:], '.Test.test') + + # "class TestCase([methodName])" + # ... + # "Each instance of TestCase will run a single test method: the + # method named methodName." + def test_init__test_name__invalid(self): + class Test(unittest.TestCase): + def runTest(self): raise MyException() + def test(self): pass + + try: + Test('testfoo') + except ValueError: + pass + else: + self.fail("Failed to raise ValueError") + + # "Return the number of tests represented by the this test object. For + # TestCase instances, this will always be 1" + def test_countTestCases(self): + class Foo(unittest.TestCase): + def test(self): pass + + self.assertEqual(Foo('test').countTestCases(), 1) + + # "Return the default type of test result object to be used to run this + # test. For TestCase instances, this will always be + # unittest.TestResult; subclasses of TestCase should + # override this as necessary." + def test_defaultTestResult(self): + class Foo(unittest.TestCase): + def runTest(self): + pass + + result = Foo().defaultTestResult() + self.assertEqual(type(result), unittest.TestResult) + + # "When a setUp() method is defined, the test runner will run that method + # prior to each test. Likewise, if a tearDown() method is defined, the + # test runner will invoke that method after each test. In the example, + # setUp() was used to create a fresh sequence for each test." + # + # Make sure the proper call order is maintained, even if setUp() raises + # an exception. + def test_run_call_order__error_in_setUp(self): + events = [] + result = LoggingResult(events) + + class Foo(unittest.TestCase): + def setUp(self): + events.append('setUp') + raise RuntimeError('raised by Foo.setUp') + + def test(self): + events.append('test') + + def tearDown(self): + events.append('tearDown') + + Foo('test').run(result) + expected = ['startTest', 'setUp', 'addError', 'stopTest'] + self.assertEqual(events, expected) + + # "When a setUp() method is defined, the test runner will run that method + # prior to each test. Likewise, if a tearDown() method is defined, the + # test runner will invoke that method after each test. In the example, + # setUp() was used to create a fresh sequence for each test." + # + # Make sure the proper call order is maintained, even if the test raises + # an error (as opposed to a failure). + def test_run_call_order__error_in_test(self): + events = [] + result = LoggingResult(events) + + class Foo(unittest.TestCase): + def setUp(self): + events.append('setUp') + + def test(self): + events.append('test') + raise RuntimeError('raised by Foo.test') + + def tearDown(self): + events.append('tearDown') + + expected = ['startTest', 'setUp', 'test', 'addError', 'tearDown', + 'stopTest'] + Foo('test').run(result) + self.assertEqual(events, expected) + + # "When a setUp() method is defined, the test runner will run that method + # prior to each test. Likewise, if a tearDown() method is defined, the + # test runner will invoke that method after each test. In the example, + # setUp() was used to create a fresh sequence for each test." + # + # Make sure the proper call order is maintained, even if the test signals + # a failure (as opposed to an error). + def test_run_call_order__failure_in_test(self): + events = [] + result = LoggingResult(events) + + class Foo(unittest.TestCase): + def setUp(self): + events.append('setUp') + + def test(self): + events.append('test') + self.fail('raised by Foo.test') + + def tearDown(self): + events.append('tearDown') + + expected = ['startTest', 'setUp', 'test', 'addFailure', 'tearDown', + 'stopTest'] + Foo('test').run(result) + self.assertEqual(events, expected) + + # "When a setUp() method is defined, the test runner will run that method + # prior to each test. Likewise, if a tearDown() method is defined, the + # test runner will invoke that method after each test. In the example, + # setUp() was used to create a fresh sequence for each test." + # + # Make sure the proper call order is maintained, even if tearDown() raises + # an exception. + def test_run_call_order__error_in_tearDown(self): + events = [] + result = LoggingResult(events) + + class Foo(unittest.TestCase): + def setUp(self): + events.append('setUp') + + def test(self): + events.append('test') + + def tearDown(self): + events.append('tearDown') + raise RuntimeError('raised by Foo.tearDown') + + Foo('test').run(result) + expected = ['startTest', 'setUp', 'test', 'tearDown', 'addError', + 'stopTest'] + self.assertEqual(events, expected) + + # "This class attribute gives the exception raised by the test() method. + # If a test framework needs to use a specialized exception, possibly to + # carry additional information, it must subclass this exception in + # order to ``play fair'' with the framework. The initial value of this + # attribute is AssertionError" + def test_failureException__default(self): + class Foo(unittest.TestCase): + def test(self): + pass + + self.failUnless(Foo('test').failureException is AssertionError) + + # "This class attribute gives the exception raised by the test() method. + # If a test framework needs to use a specialized exception, possibly to + # carry additional information, it must subclass this exception in + # order to ``play fair'' with the framework." + # + # Make sure TestCase.run() respects the designated failureException + def test_failureException__subclassing__explicit_raise(self): + events = [] + result = LoggingResult(events) + + class Foo(unittest.TestCase): + def test(self): + raise RuntimeError() + + failureException = RuntimeError + + self.failUnless(Foo('test').failureException is RuntimeError) + + + Foo('test').run(result) + expected = ['startTest', 'addFailure', 'stopTest'] + self.assertEqual(events, expected) + + # "This class attribute gives the exception raised by the test() method. + # If a test framework needs to use a specialized exception, possibly to + # carry additional information, it must subclass this exception in + # order to ``play fair'' with the framework." + # + # Make sure TestCase.run() respects the designated failureException + def test_failureException__subclassing__implicit_raise(self): + events = [] + result = LoggingResult(events) + + class Foo(unittest.TestCase): + def test(self): + self.fail("foo") + + failureException = RuntimeError + + self.failUnless(Foo('test').failureException is RuntimeError) + + + Foo('test').run(result) + expected = ['startTest', 'addFailure', 'stopTest'] + self.assertEqual(events, expected) + + # "The default implementation does nothing." + def test_setUp(self): + class Foo(unittest.TestCase): + def runTest(self): + pass + + # ... and nothing should happen + Foo().setUp() + + # "The default implementation does nothing." + def test_tearDown(self): + class Foo(unittest.TestCase): + def runTest(self): + pass + + # ... and nothing should happen + Foo().tearDown() + + # "Return a string identifying the specific test case." + # + # Because of the vague nature of the docs, I'm not going to lock this + # test down too much. Really all that can be asserted is that the id() + # will be a string (either 8-byte or unicode -- again, because the docs + # just say "string") + def test_id(self): + class Foo(unittest.TestCase): + def runTest(self): + pass + + self.failUnless(isinstance(Foo().id(), basestring)) + + # "Returns a one-line description of the test, or None if no description + # has been provided. The default implementation of this method returns + # the first line of the test method's docstring, if available, or None." + def test_shortDescription__no_docstring(self): + class Foo(unittest.TestCase): + def runTest(self): + pass + + self.assertEqual(Foo().shortDescription(), None) + + # "Returns a one-line description of the test, or None if no description + # has been provided. The default implementation of this method returns + # the first line of the test method's docstring, if available, or None." + def test_shortDescription__singleline_docstring(self): + class Foo(unittest.TestCase): + def runTest(self): + "this tests foo" + pass + + self.assertEqual(Foo().shortDescription(), "this tests foo") + + # "Returns a one-line description of the test, or None if no description + # has been provided. The default implementation of this method returns + # the first line of the test method's docstring, if available, or None." + def test_shortDescription__multiline_docstring(self): + class Foo(unittest.TestCase): + def runTest(self): + """this tests foo + blah, bar and baz are also tested""" + pass + + self.assertEqual(Foo().shortDescription(), "this tests foo") + + # "If result is omitted or None, a temporary result object is created + # and used, but is not made available to the caller" + def test_run__uses_defaultTestResult(self): + events = [] + + class Foo(unittest.TestCase): + def test(self): + events.append('test') + + def defaultTestResult(self): + return LoggingResult(events) -def test_TestSuite_iter(): - """ - >>> test1 = unittest.FunctionTestCase(lambda: None) - >>> test2 = unittest.FunctionTestCase(lambda: None) - >>> suite = unittest.TestSuite((test1, test2)) - >>> tests = [] - >>> for test in suite: - ... tests.append(test) - >>> tests == [test1, test2] - True - """ + # Make run() find a result object on its own + Foo('test').run() + expected = ['startTest', 'test', 'stopTest'] + self.assertEqual(events, expected) ###################################################################### ## Main ###################################################################### def test_main(): - from test import test_support, test_unittest - test_support.run_doctest(test_unittest, verbosity=True) + test_support.run_unittest(Test_TestCase, Test_TestLoader, + Test_TestSuite, Test_TestResult, Test_FunctionTestCase) -if __name__ == '__main__': +if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_unpack.py ============================================================================== --- python/branches/p3yk/Lib/test/test_unpack.py (original) +++ python/branches/p3yk/Lib/test/test_unpack.py Fri Apr 27 21:54:29 2007 @@ -55,7 +55,7 @@ >>> a, b, c = 7 Traceback (most recent call last): ... - TypeError: unpack non-sequence + TypeError: 'int' object is not iterable Unpacking tuple of wrong size Modified: python/branches/p3yk/Lib/test/test_urllib.py ============================================================================== --- python/branches/p3yk/Lib/test/test_urllib.py (original) +++ python/branches/p3yk/Lib/test/test_urllib.py Fri Apr 27 21:54:29 2007 @@ -122,6 +122,15 @@ finally: self.unfakehttp() + def test_empty_socket(self): + """urlopen() raises IOError if the underlying socket does not send any + data. (#1680230) """ + self.fakehttp('') + try: + self.assertRaises(IOError, urllib.urlopen, 'http://something') + finally: + self.unfakehttp() + class urlretrieve_FileTests(unittest.TestCase): """Test urllib.urlretrieve() on local files""" Modified: python/branches/p3yk/Lib/test/test_urllib2.py ============================================================================== --- python/branches/p3yk/Lib/test/test_urllib2.py (original) +++ python/branches/p3yk/Lib/test/test_urllib2.py Fri Apr 27 21:54:29 2007 @@ -625,11 +625,11 @@ for url in [ "file://localhost:80%s" % urlpath, -# XXXX bug: these fail with socket.gaierror, should be URLError -## "file://%s:80%s/%s" % (socket.gethostbyname('localhost'), -## os.getcwd(), TESTFN), -## "file://somerandomhost.ontheinternet.com%s/%s" % -## (os.getcwd(), TESTFN), + "file:///file_does_not_exist.txt", + "file://%s:80%s/%s" % (socket.gethostbyname('localhost'), + os.getcwd(), TESTFN), + "file://somerandomhost.ontheinternet.com%s/%s" % + (os.getcwd(), TESTFN), ]: try: f = open(TESTFN, "wb") @@ -765,16 +765,24 @@ url = "http://example.com/" req = Request(url) - # 200 OK is passed through + # all 2xx are passed through r = MockResponse(200, "OK", {}, "", url) newr = h.http_response(req, r) self.assert_(r is newr) self.assert_(not hasattr(o, "proto")) # o.error not called + r = MockResponse(202, "Accepted", {}, "", url) + newr = h.http_response(req, r) + self.assert_(r is newr) + self.assert_(not hasattr(o, "proto")) # o.error not called + r = MockResponse(206, "Partial content", {}, "", url) + newr = h.http_response(req, r) + self.assert_(r is newr) + self.assert_(not hasattr(o, "proto")) # o.error not called # anything else calls o.error (and MockOpener returns None, here) - r = MockResponse(201, "Created", {}, "", url) + r = MockResponse(502, "Bad gateway", {}, "", url) self.assert_(h.http_response(req, r) is None) self.assertEqual(o.proto, "http") # o.error called - self.assertEqual(o.args, (req, r, 201, "Created", {})) + self.assertEqual(o.args, (req, r, 502, "Bad gateway", {})) def test_cookies(self): cj = MockCookieJar() Modified: python/branches/p3yk/Lib/test/test_urllib2net.py ============================================================================== --- python/branches/p3yk/Lib/test/test_urllib2net.py (original) +++ python/branches/p3yk/Lib/test/test_urllib2net.py Fri Apr 27 21:54:29 2007 @@ -264,7 +264,8 @@ (expected_err, url, req, err)) self.assert_(isinstance(err, expected_err), msg) else: - buf = f.read() + with test_support.transient_internet(): + buf = f.read() f.close() debug("read %d bytes" % len(buf)) debug("******** next url coming up...") Modified: python/branches/p3yk/Lib/test/test_userdict.py ============================================================================== --- python/branches/p3yk/Lib/test/test_userdict.py (original) +++ python/branches/p3yk/Lib/test/test_userdict.py Fri Apr 27 21:54:29 2007 @@ -171,7 +171,7 @@ except RuntimeError as err: self.assertEqual(err.args, (42,)) else: - self.fail_("e[42] didn't raise RuntimeError") + self.fail("e[42] didn't raise RuntimeError") class F(UserDict.UserDict): def __init__(self): # An instance variable __missing__ should have no effect @@ -183,7 +183,7 @@ except KeyError as err: self.assertEqual(err.args, (42,)) else: - self.fail_("f[42] didn't raise KeyError") + self.fail("f[42] didn't raise KeyError") class G(UserDict.UserDict): pass g = G() @@ -192,7 +192,7 @@ except KeyError as err: self.assertEqual(err.args, (42,)) else: - self.fail_("g[42] didn't raise KeyError") + self.fail("g[42] didn't raise KeyError") ########################## # Test Dict Mixin Modified: python/branches/p3yk/Lib/test/test_warnings.py ============================================================================== --- python/branches/p3yk/Lib/test/test_warnings.py (original) +++ python/branches/p3yk/Lib/test/test_warnings.py Fri Apr 27 21:54:29 2007 @@ -3,95 +3,97 @@ import unittest from test import test_support -# The warnings module isn't easily tested, because it relies on module -# globals to store configuration information. setUp() and tearDown() -# preserve the current settings to avoid bashing them while running tests. - -# To capture the warning messages, a replacement for showwarning() is -# used to save warning information in a global variable. - -class WarningMessage: - "Holds results of latest showwarning() call" - pass - -def showwarning(message, category, filename, lineno, file=None): - msg.message = str(message) - msg.category = category.__name__ - msg.filename = os.path.basename(filename) - msg.lineno = lineno +import warning_tests class TestModule(unittest.TestCase): - def setUp(self): - global msg - msg = WarningMessage() - self._filters = warnings.filters[:] - self._showwarning = warnings.showwarning - warnings.showwarning = showwarning - self.ignored = [w[2].__name__ for w in self._filters + self.ignored = [w[2].__name__ for w in warnings.filters if w[0]=='ignore' and w[1] is None and w[3] is None] - def tearDown(self): - warnings.filters = self._filters[:] - warnings.showwarning = self._showwarning - def test_warn_default_category(self): - for i in range(4): - text = 'multi %d' %i # Different text on each call - warnings.warn(text) - self.assertEqual(msg.message, text) - self.assertEqual(msg.category, 'UserWarning') + with test_support.catch_warning() as w: + for i in range(4): + text = 'multi %d' %i # Different text on each call + warnings.warn(text) + self.assertEqual(str(w.message), text) + self.assert_(w.category is UserWarning) def test_warn_specific_category(self): - text = 'None' - for category in [DeprecationWarning, FutureWarning, - PendingDeprecationWarning, RuntimeWarning, - SyntaxWarning, UserWarning, Warning]: - if category.__name__ in self.ignored: - text = 'filtered out' + category.__name__ - warnings.warn(text, category) - self.assertNotEqual(msg.message, text) - else: - text = 'unfiltered %s' % category.__name__ - warnings.warn(text, category) - self.assertEqual(msg.message, text) - self.assertEqual(msg.category, category.__name__) + with test_support.catch_warning() as w: + text = 'None' + for category in [DeprecationWarning, FutureWarning, + PendingDeprecationWarning, RuntimeWarning, + SyntaxWarning, UserWarning, Warning]: + if category.__name__ in self.ignored: + text = 'filtered out' + category.__name__ + warnings.warn(text, category) + self.assertNotEqual(w.message, text) + else: + text = 'unfiltered %s' % category.__name__ + warnings.warn(text, category) + self.assertEqual(str(w.message), text) + self.assert_(w.category is category) def test_filtering(self): + with test_support.catch_warning() as w: + warnings.filterwarnings("error", "", Warning, "", 0) + self.assertRaises(UserWarning, warnings.warn, 'convert to error') + + warnings.resetwarnings() + text = 'handle normally' + warnings.warn(text) + self.assertEqual(str(w.message), text) + self.assert_(w.category is UserWarning) - warnings.filterwarnings("error", "", Warning, "", 0) - self.assertRaises(UserWarning, warnings.warn, 'convert to error') + warnings.filterwarnings("ignore", "", Warning, "", 0) + text = 'filtered out' + warnings.warn(text) + self.assertNotEqual(str(w.message), text) - warnings.resetwarnings() - text = 'handle normally' - warnings.warn(text) - self.assertEqual(msg.message, text) - self.assertEqual(msg.category, 'UserWarning') - - warnings.filterwarnings("ignore", "", Warning, "", 0) - text = 'filtered out' - warnings.warn(text) - self.assertNotEqual(msg.message, text) - - warnings.resetwarnings() - warnings.filterwarnings("error", "hex*", Warning, "", 0) - self.assertRaises(UserWarning, warnings.warn, 'hex/oct') - text = 'nonmatching text' - warnings.warn(text) - self.assertEqual(msg.message, text) - self.assertEqual(msg.category, 'UserWarning') + warnings.resetwarnings() + warnings.filterwarnings("error", "hex*", Warning, "", 0) + self.assertRaises(UserWarning, warnings.warn, 'hex/oct') + text = 'nonmatching text' + warnings.warn(text) + self.assertEqual(str(w.message), text) + self.assert_(w.category is UserWarning) def test_options(self): # Uses the private _setoption() function to test the parsing # of command-line warning arguments - self.assertRaises(warnings._OptionError, - warnings._setoption, '1:2:3:4:5:6') - self.assertRaises(warnings._OptionError, - warnings._setoption, 'bogus::Warning') - self.assertRaises(warnings._OptionError, - warnings._setoption, 'ignore:2::4:-5') - warnings._setoption('error::Warning::0') - self.assertRaises(UserWarning, warnings.warn, 'convert to error') + with test_support.guard_warnings_filter(): + self.assertRaises(warnings._OptionError, + warnings._setoption, '1:2:3:4:5:6') + self.assertRaises(warnings._OptionError, + warnings._setoption, 'bogus::Warning') + self.assertRaises(warnings._OptionError, + warnings._setoption, 'ignore:2::4:-5') + warnings._setoption('error::Warning::0') + self.assertRaises(UserWarning, warnings.warn, 'convert to error') + + def test_filename(self): + with test_support.catch_warning() as w: + warning_tests.inner("spam1") + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") + warning_tests.outer("spam2") + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") + + def test_stacklevel(self): + # Test stacklevel argument + # make sure all messages are different, so the warning won't be skipped + with test_support.catch_warning() as w: + warning_tests.inner("spam3", stacklevel=1) + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") + warning_tests.outer("spam4", stacklevel=1) + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") + + warning_tests.inner("spam5", stacklevel=2) + self.assertEqual(os.path.basename(w.filename), "test_warnings.py") + warning_tests.outer("spam6", stacklevel=2) + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") + + warning_tests.inner("spam7", stacklevel=9999) + self.assertEqual(os.path.basename(w.filename), "sys") def test_main(verbose=None): Modified: python/branches/p3yk/Lib/test/test_weakref.py ============================================================================== --- python/branches/p3yk/Lib/test/test_weakref.py (original) +++ python/branches/p3yk/Lib/test/test_weakref.py Fri Apr 27 21:54:29 2007 @@ -841,7 +841,7 @@ items = dict.items() for item in dict.items(): items.remove(item) - self.assert_(len(items) == 0, "iteritems() did not touch all items") + self.assert_(len(items) == 0, "items() did not touch all items") # key iterator, via __iter__(): keys = list(dict.keys()) @@ -1104,7 +1104,7 @@ ... self.__counter += 1 ... ob = (ob, self.__counter) ... return ob -... +... >>> class A: # not in docs from here, just testing the ExtendedRef ... pass ... Modified: python/branches/p3yk/Lib/test/test_wsgiref.py ============================================================================== --- python/branches/p3yk/Lib/test/test_wsgiref.py (original) +++ python/branches/p3yk/Lib/test/test_wsgiref.py Fri Apr 27 21:54:29 2007 @@ -1,5 +1,5 @@ from __future__ import nested_scopes # Backward compat for 2.1 -from unittest import TestSuite, TestCase, makeSuite +from unittest import TestCase from wsgiref.util import setup_testing_defaults from wsgiref.headers import Headers from wsgiref.handlers import BaseHandler, BaseCGIHandler @@ -11,6 +11,7 @@ from SocketServer import BaseServer import re, sys +from test import test_support class MockServer(WSGIServer): """Non-socket HTTP server""" @@ -575,11 +576,7 @@ # This epilogue is needed for compatibility with the Python 2.5 regrtest module def test_main(): - import unittest - from test.test_support import run_suite - run_suite( - unittest.defaultTestLoader.loadTestsFromModule(sys.modules[__name__]) - ) + test_support.run_unittest(__name__) if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Lib/test/test_zipfile.py ============================================================================== --- python/branches/p3yk/Lib/test/test_zipfile.py (original) +++ python/branches/p3yk/Lib/test/test_zipfile.py Fri Apr 27 21:54:29 2007 @@ -4,26 +4,30 @@ except ImportError: zlib = None -import zipfile, os, unittest, sys, shutil +import zipfile, os, unittest, sys, shutil, struct from StringIO import StringIO from tempfile import TemporaryFile +from random import randint, random +import test.test_support as support from test.test_support import TESTFN, run_unittest TESTFN2 = TESTFN + "2" +FIXEDTEST_SIZE = 10 class TestsWithSourceFile(unittest.TestCase): def setUp(self): - line_gen = ("Test of zipfile line %d." % i for i in range(0, 1000)) - self.data = '\n'.join(line_gen) + self.line_gen = ("Zipfile test line %d. random float: %f" % (i, random()) + for i in xrange(FIXEDTEST_SIZE)) + self.data = '\n'.join(self.line_gen) + '\n' # Make a source file with some lines fp = open(TESTFN, "wb") fp.write(self.data) fp.close() - def zipTest(self, f, compression): + def makeTestArchive(self, f, compression): # Create the ZIP archive zipfp = zipfile.ZipFile(f, "w", compression) zipfp.write(TESTFN, "another"+os.extsep+"name") @@ -31,6 +35,9 @@ zipfp.writestr("strfile", self.data) zipfp.close() + def zipTest(self, f, compression): + self.makeTestArchive(f, compression) + # Read the ZIP archive zipfp = zipfile.ZipFile(f, "r", compression) self.assertEqual(zipfp.read(TESTFN), self.data) @@ -85,22 +92,144 @@ # Check that testzip doesn't raise an exception zipfp.testzip() + zipfp.close() + def testStored(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipTest(f, zipfile.ZIP_STORED) + + def zipOpenTest(self, f, compression): + self.makeTestArchive(f, compression) + # Read the ZIP archive + zipfp = zipfile.ZipFile(f, "r", compression) + zipdata1 = [] + zipopen1 = zipfp.open(TESTFN) + while 1: + read_data = zipopen1.read(256) + if not read_data: + break + zipdata1.append(read_data) + + zipdata2 = [] + zipopen2 = zipfp.open("another"+os.extsep+"name") + while 1: + read_data = zipopen2.read(256) + if not read_data: + break + zipdata2.append(read_data) + + self.assertEqual(''.join(zipdata1), self.data) + self.assertEqual(''.join(zipdata2), self.data) zipfp.close() + def testOpenStored(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipOpenTest(f, zipfile.ZIP_STORED) + def zipRandomOpenTest(self, f, compression): + self.makeTestArchive(f, compression) + # Read the ZIP archive + zipfp = zipfile.ZipFile(f, "r", compression) + zipdata1 = [] + zipopen1 = zipfp.open(TESTFN) + while 1: + read_data = zipopen1.read(randint(1, 1024)) + if not read_data: + break + zipdata1.append(read_data) - def testStored(self): + self.assertEqual(''.join(zipdata1), self.data) + zipfp.close() + + def testRandomOpenStored(self): for f in (TESTFN2, TemporaryFile(), StringIO()): - self.zipTest(f, zipfile.ZIP_STORED) + self.zipRandomOpenTest(f, zipfile.ZIP_STORED) + + def zipReadlineTest(self, f, compression): + self.makeTestArchive(f, compression) + + # Read the ZIP archive + zipfp = zipfile.ZipFile(f, "r") + zipopen = zipfp.open(TESTFN) + for line in self.line_gen: + linedata = zipopen.readline() + self.assertEqual(linedata, line + '\n') + + zipfp.close() + + def zipReadlinesTest(self, f, compression): + self.makeTestArchive(f, compression) + + # Read the ZIP archive + zipfp = zipfile.ZipFile(f, "r") + ziplines = zipfp.open(TESTFN).readlines() + for line, zipline in zip(self.line_gen, ziplines): + self.assertEqual(zipline, line + '\n') + + zipfp.close() + + def zipIterlinesTest(self, f, compression): + self.makeTestArchive(f, compression) + + # Read the ZIP archive + zipfp = zipfile.ZipFile(f, "r") + for line, zipline in zip(self.line_gen, zipfp.open(TESTFN)): + self.assertEqual(zipline, line + '\n') + + zipfp.close() + + def testReadlineStored(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipReadlineTest(f, zipfile.ZIP_STORED) + + def testReadlinesStored(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipReadlinesTest(f, zipfile.ZIP_STORED) + + def testIterlinesStored(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipIterlinesTest(f, zipfile.ZIP_STORED) if zlib: def testDeflated(self): for f in (TESTFN2, TemporaryFile(), StringIO()): self.zipTest(f, zipfile.ZIP_DEFLATED) + def testOpenDeflated(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipOpenTest(f, zipfile.ZIP_DEFLATED) + + def testRandomOpenDeflated(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipRandomOpenTest(f, zipfile.ZIP_DEFLATED) + + def testReadlineDeflated(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipReadlineTest(f, zipfile.ZIP_DEFLATED) + + def testReadlinesDeflated(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipReadlinesTest(f, zipfile.ZIP_DEFLATED) + + def testIterlinesDeflated(self): + for f in (TESTFN2, TemporaryFile(), StringIO()): + self.zipIterlinesTest(f, zipfile.ZIP_DEFLATED) + + def testLowCompression(self): + # Checks for cases where compressed data is larger than original + # Create the ZIP archive + zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED) + zipfp.writestr("strfile", '12') + zipfp.close() + + # Get an open object for strfile + zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED) + openobj = zipfp.open("strfile") + self.assertEqual(openobj.read(1), '1') + self.assertEqual(openobj.read(1), '2') + def testAbsoluteArcnames(self): zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) zipfp.write(TESTFN, "/absolute") @@ -110,7 +239,6 @@ self.assertEqual(zipfp.namelist(), ["absolute"]) zipfp.close() - def tearDown(self): os.remove(TESTFN) os.remove(TESTFN2) @@ -123,7 +251,7 @@ self._limit = zipfile.ZIP64_LIMIT zipfile.ZIP64_LIMIT = 5 - line_gen = ("Test of zipfile line %d." % i for i in range(0, 1000)) + line_gen = ("Test of zipfile line %d." % i for i in range(0, FIXEDTEST_SIZE)) self.data = '\n'.join(line_gen) # Make a source file with some lines @@ -310,10 +438,10 @@ def testCreateNonExistentFileForAppend(self): if os.path.exists(TESTFN): os.unlink(TESTFN) - + filename = 'testfile.txt' content = 'hello, world. this is some content.' - + try: zf = zipfile.ZipFile(TESTFN, 'a') zf.writestr(filename, content) @@ -326,9 +454,7 @@ zf = zipfile.ZipFile(TESTFN, 'r') self.assertEqual(zf.read(filename), content) zf.close() - - os.unlink(TESTFN) - + def testCloseErroneousFile(self): # This test checks that the ZipFile constructor closes the file object # it opens if there's an error in the file. If it doesn't, the traceback @@ -342,7 +468,25 @@ try: zf = zipfile.ZipFile(TESTFN) except zipfile.BadZipfile: - os.unlink(TESTFN) + pass + + def testIsZipErroneousFile(self): + # This test checks that the is_zipfile function correctly identifies + # a file that is not a zip file + fp = open(TESTFN, "w") + fp.write("this is not a legal zip file\n") + fp.close() + chk = zipfile.is_zipfile(TESTFN) + self.assert_(chk is False) + + def testIsZipValidFile(self): + # This test checks that the is_zipfile function correctly identifies + # a file that is a zip file + zipf = zipfile.ZipFile(TESTFN, mode="w") + zipf.writestr("foo.txt", "O, for a Muse of Fire!") + zipf.close() + chk = zipfile.is_zipfile(TESTFN) + self.assert_(chk is True) def testNonExistentFileRaisesIOError(self): # make sure we don't raise an AttributeError when a partially-constructed @@ -371,6 +515,9 @@ # and report that the first file in the archive was corrupt. self.assertRaises(RuntimeError, zipf.testzip) + def tearDown(self): + support.unlink(TESTFN) + support.unlink(TESTFN2) class DecryptionTests(unittest.TestCase): # This test checks that ZIP decryption works. Since the library does not @@ -406,15 +553,265 @@ def testBadPassword(self): self.zip.setpassword("perl") self.assertRaises(RuntimeError, self.zip.read, "test.txt") - + def testGoodPassword(self): self.zip.setpassword("python") self.assertEquals(self.zip.read("test.txt"), self.plain) + +class TestsWithRandomBinaryFiles(unittest.TestCase): + def setUp(self): + datacount = randint(16, 64)*1024 + randint(1, 1024) + self.data = ''.join((struct.pack('' + return False + else: + return True _tryorder = [] _browsers = {} - # Prefer mozilla/netscape/opera if present + + # First try to use the default Windows browser + register("windows-default", WindowsDefault) + + # Detect some common Windows browsers, fallback to IE + iexplore = os.path.join(os.environ.get("PROGRAMFILES", "C:\\Program Files"), + "Internet Explorer\\IEXPLORE.EXE") for browser in ("firefox", "firebird", "seamonkey", "mozilla", - "netscape", "opera"): + "netscape", "opera", iexplore): if _iscommand(browser): register(browser, None, BackgroundBrowser(browser)) - register("windows-default", WindowsDefault) # # Platform support for MacOS Modified: python/branches/p3yk/Lib/zipfile.py ============================================================================== --- python/branches/p3yk/Lib/zipfile.py (original) +++ python/branches/p3yk/Lib/zipfile.py Fri Apr 27 21:54:29 2007 @@ -361,6 +361,200 @@ self._UpdateKeys(c) return c +class ZipExtFile: + """File-like object for reading an archive member. + Is returned by ZipFile.open(). + """ + + def __init__(self, fileobj, zipinfo, decrypt=None): + self.fileobj = fileobj + self.decrypter = decrypt + self.bytes_read = 0 + self.rawbuffer = '' + self.readbuffer = '' + self.linebuffer = '' + self.eof = False + self.univ_newlines = False + self.nlSeps = ("\n", ) + self.lastdiscard = '' + + self.compress_type = zipinfo.compress_type + self.compress_size = zipinfo.compress_size + + self.closed = False + self.mode = "r" + self.name = zipinfo.filename + + # read from compressed files in 64k blocks + self.compreadsize = 64*1024 + if self.compress_type == ZIP_DEFLATED: + self.dc = zlib.decompressobj(-15) + + def set_univ_newlines(self, univ_newlines): + self.univ_newlines = univ_newlines + + # pick line separator char(s) based on universal newlines flag + self.nlSeps = ("\n", ) + if self.univ_newlines: + self.nlSeps = ("\r\n", "\r", "\n") + + def __iter__(self): + return self + + def __next__(self): + nextline = self.readline() + if not nextline: + raise StopIteration() + + return nextline + + def close(self): + self.closed = True + + def _checkfornewline(self): + nl, nllen = -1, -1 + if self.linebuffer: + # ugly check for cases where half of an \r\n pair was + # read on the last pass, and the \r was discarded. In this + # case we just throw away the \n at the start of the buffer. + if (self.lastdiscard, self.linebuffer[0]) == ('\r','\n'): + self.linebuffer = self.linebuffer[1:] + + for sep in self.nlSeps: + nl = self.linebuffer.find(sep) + if nl >= 0: + nllen = len(sep) + return nl, nllen + + return nl, nllen + + def readline(self, size = -1): + """Read a line with approx. size. If size is negative, + read a whole line. + """ + if size < 0: + size = sys.maxint + elif size == 0: + return '' + + # check for a newline already in buffer + nl, nllen = self._checkfornewline() + + if nl >= 0: + # the next line was already in the buffer + nl = min(nl, size) + else: + # no line break in buffer - try to read more + size -= len(self.linebuffer) + while nl < 0 and size > 0: + buf = self.read(min(size, 100)) + if not buf: + break + self.linebuffer += buf + size -= len(buf) + + # check for a newline in buffer + nl, nllen = self._checkfornewline() + + # we either ran out of bytes in the file, or + # met the specified size limit without finding a newline, + # so return current buffer + if nl < 0: + s = self.linebuffer + self.linebuffer = '' + return s + + buf = self.linebuffer[:nl] + self.lastdiscard = self.linebuffer[nl:nl + nllen] + self.linebuffer = self.linebuffer[nl + nllen:] + + # line is always returned with \n as newline char (except possibly + # for a final incomplete line in the file, which is handled above). + return buf + "\n" + + def readlines(self, sizehint = -1): + """Return a list with all (following) lines. The sizehint parameter + is ignored in this implementation. + """ + result = [] + while True: + line = self.readline() + if not line: break + result.append(line) + return result + + def read(self, size = None): + # act like file() obj and return empty string if size is 0 + if size == 0: + return '' + + # determine read size + bytesToRead = self.compress_size - self.bytes_read + + # adjust read size for encrypted files since the first 12 bytes + # are for the encryption/password information + if self.decrypter is not None: + bytesToRead -= 12 + + if size is not None and size >= 0: + if self.compress_type == ZIP_STORED: + lr = len(self.readbuffer) + bytesToRead = min(bytesToRead, size - lr) + elif self.compress_type == ZIP_DEFLATED: + if len(self.readbuffer) > size: + # the user has requested fewer bytes than we've already + # pulled through the decompressor; don't read any more + bytesToRead = 0 + else: + # user will use up the buffer, so read some more + lr = len(self.rawbuffer) + bytesToRead = min(bytesToRead, self.compreadsize - lr) + + # avoid reading past end of file contents + if bytesToRead + self.bytes_read > self.compress_size: + bytesToRead = self.compress_size - self.bytes_read + + # try to read from file (if necessary) + if bytesToRead > 0: + bytes = self.fileobj.read(bytesToRead) + self.bytes_read += len(bytes) + self.rawbuffer += bytes + + # handle contents of raw buffer + if self.rawbuffer: + newdata = self.rawbuffer + self.rawbuffer = '' + + # decrypt new data if we were given an object to handle that + if newdata and self.decrypter is not None: + newdata = ''.join(map(self.decrypter, newdata)) + + # decompress newly read data if necessary + if newdata and self.compress_type == ZIP_DEFLATED: + newdata = self.dc.decompress(newdata) + self.rawbuffer = self.dc.unconsumed_tail + if self.eof and len(self.rawbuffer) == 0: + # we're out of raw bytes (both from the file and + # the local buffer); flush just to make sure the + # decompressor is done + newdata += self.dc.flush() + # prevent decompressor from being used again + self.dc = None + + self.readbuffer += newdata + + + # return what the user asked for + if size is None or len(self.readbuffer) <= size: + bytes = self.readbuffer + self.readbuffer = '' + else: + bytes = self.readbuffer[:size] + self.readbuffer = self.readbuffer[size:] + + return bytes + + class ZipFile: """ Class with methods to open, read, write, close, list zip files. @@ -540,73 +734,75 @@ def read(self, name, pwd=None): """Return file bytes (as a string) for name.""" - if self.mode not in ("r", "a"): - raise RuntimeError, 'read() requires mode "r" or "a"' + return self.open(name, "r", pwd).read() + + def open(self, name, mode="r", pwd=None): + """Return file-like object for 'name'.""" + if mode not in ("r", "U", "rU"): + raise RuntimeError, 'open() requires mode "r", "U", or "rU"' if not self.fp: raise RuntimeError, \ "Attempt to read ZIP archive that was already closed" + + # Only open a new file for instances where we were not + # given a file object in the constructor + if self._filePassed: + zef_file = self.fp + else: + zef_file = open(self.filename, 'rb') + + # Get info object for name zinfo = self.getinfo(name) - is_encrypted = zinfo.flag_bits & 0x1 - if is_encrypted: - if not pwd: - pwd = self.pwd - if not pwd: - raise RuntimeError, "File %s is encrypted, " \ - "password required for extraction" % name - filepos = self.fp.tell() - self.fp.seek(zinfo.header_offset, 0) + filepos = zef_file.tell() + + zef_file.seek(zinfo.header_offset, 0) # Skip the file header: - fheader = self.fp.read(30) + fheader = zef_file.read(30) if fheader[0:4] != stringFileHeader: raise BadZipfile, "Bad magic number for file header" fheader = struct.unpack(structFileHeader, fheader) - fname = self.fp.read(fheader[_FH_FILENAME_LENGTH]) + fname = zef_file.read(fheader[_FH_FILENAME_LENGTH]) if fheader[_FH_EXTRA_FIELD_LENGTH]: - self.fp.read(fheader[_FH_EXTRA_FIELD_LENGTH]) + zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH]) if fname != zinfo.orig_filename: raise BadZipfile, \ 'File name in directory "%s" and header "%s" differ.' % ( zinfo.orig_filename, fname) - bytes = self.fp.read(zinfo.compress_size) - # Go with decryption + # check for encrypted flag & handle password + is_encrypted = zinfo.flag_bits & 0x1 + zd = None if is_encrypted: + if not pwd: + pwd = self.pwd + if not pwd: + raise RuntimeError, "File %s is encrypted, " \ + "password required for extraction" % name + zd = _ZipDecrypter(pwd) # The first 12 bytes in the cypher stream is an encryption header # used to strengthen the algorithm. The first 11 bytes are # completely random, while the 12th contains the MSB of the CRC, # and is used to check the correctness of the password. + bytes = zef_file.read(12) h = map(zd, bytes[0:12]) if ord(h[11]) != ((zinfo.CRC>>24)&255): raise RuntimeError, "Bad password for file %s" % name - bytes = "".join(map(zd, bytes[12:])) - # Go with decompression - self.fp.seek(filepos, 0) - if zinfo.compress_type == ZIP_STORED: - pass - elif zinfo.compress_type == ZIP_DEFLATED: - if not zlib: - raise RuntimeError, \ - "De-compression requires the (missing) zlib module" - # zlib compress/decompress code by Jeremy Hylton of CNRI - dc = zlib.decompressobj(-15) - bytes = dc.decompress(bytes) - # need to feed in unused pad byte so that zlib won't choke - ex = dc.decompress('Z') + dc.flush() - if ex: - bytes = bytes + ex - else: - raise BadZipfile, \ - "Unsupported compression method %d for file %s" % \ - (zinfo.compress_type, name) - crc = binascii.crc32(bytes) - if crc != zinfo.CRC: - raise BadZipfile, "Bad CRC-32 for file %s" % name - return bytes + + # build and return a ZipExtFile + if zd is None: + zef = ZipExtFile(zef_file, zinfo) + else: + zef = ZipExtFile(zef_file, zinfo, zd) + + # set universal newlines on ZipExtFile if necessary + if "U" in mode: + zef.set_univ_newlines(True) + return zef def _writecheck(self, zinfo): """Check for errors before writing a file to the archive.""" Modified: python/branches/p3yk/Misc/ACKS ============================================================================== --- python/branches/p3yk/Misc/ACKS (original) +++ python/branches/p3yk/Misc/ACKS Fri Apr 27 21:54:29 2007 @@ -29,12 +29,14 @@ Donovan Baarda Attila Babo Alfonso Baciero +Dwayne Bailey Stig Bakken Greg Ball Luigi Ballabio Michael J. Barber Chris Barker Quentin Barnes +Richard Barran Cesar Eduardo Barros Des Barry Ulf Bartelt @@ -106,6 +108,7 @@ Brett Cannon Mike Carlton Terry Carroll +Brian Leair Luke Kenneth Casson Leighton Donn Cave Per Cederqvist @@ -154,8 +157,10 @@ Jonathan Dasteel John DeGood Vincent Delft +Erik Demaine Roger Dev Toby Dickenson +Mark Dickinson Yves Dionne Daniel Dittmar Walter D?rwald @@ -200,6 +205,7 @@ Niels Ferguson Sebastian Fernandez Vincent Fiack +Tomer Filiba Russell Finn Nils Fischbeck Frederik Fix @@ -216,6 +222,7 @@ Peter Funk Geoff Furnish Lele Gaifax +Santiago Gala Yitzchak Gale Raymund Galvin Nitin Ganatra @@ -239,6 +246,7 @@ Eddy De Greef Duncan Grisby Dag Gruneau +Thomas G?ttler Michael Guravage Lars Gust?bel Barry Haddow @@ -270,6 +278,7 @@ Ivan Herman J?rgen Hermann Gary Herron +Thomas Herve Bernhard Herzog Magnus L. Hetland Raymond Hettinger @@ -324,6 +333,7 @@ Gregory K. Johnson Simon Johnston Evan Jones +Jeremy Jones Richard Jones Irmen de Jong Lucas de Jonge @@ -353,9 +363,11 @@ Lenny Kneler Pat Knight Greg Kochanski +Damon Kohler Joseph Koshy Bob Kras Holger Krekel +Fabian Kreutz Hannu Krosing Andrew Kuchling Vladimir Kushnir @@ -383,6 +395,7 @@ Martin Ligr Christopher Lindblad Eric Lindvall +Bjorn Lindqvist Per Lindqvist Nick Lockwood Stephanie Lockwood @@ -408,6 +421,7 @@ Doug Marien Alex Martelli Anthony Martin +S?bastien Martini Roger Masse Nick Mathewson Graham Matthews @@ -427,8 +441,10 @@ Steven Miale Trent Mick Chad Miller +Damien Miller Roman Milner Dom Mitchell +Dustin J. Mitchell Doug Moen Paul Moore The Dragon De Monsyne @@ -468,6 +484,7 @@ Mike Pall Todd R. Palmer Jan Palus +Peter Parente Alexandre Parenteau Dan Parisien Harri Pasanen @@ -555,6 +572,7 @@ Gregor Schmid Ralf Schmitt Peter Schneider-Kamp +Arvin Schnell Chad J. Schroeder Sam Schulenburg Stefan Schwarzer @@ -565,6 +583,7 @@ ??iga Seilnach Fred Sells Jiwon Seo +Jerry Seutter Denis Severson Ha Shao Bruce Sherwood @@ -689,6 +708,7 @@ Richard Wolff Gordon Worley Thomas Wouters +Heiko Wundram Doug Wyatt Ka-Ping Yee Bob Yodlowski Modified: python/branches/p3yk/Misc/NEWS ============================================================================== --- python/branches/p3yk/Misc/NEWS (original) +++ python/branches/p3yk/Misc/NEWS Fri Apr 27 21:54:29 2007 @@ -18,7 +18,7 @@ - Unify range() and xrange(). -- Rework the standard I/O library to use bytes for binary files. +- Use io.py instead of C stdio everywhere. - Make strings all Unicode. @@ -28,6 +28,8 @@ Core and Builtins ----------------- +- Merged from (2.6) trunk at r54987. + - Patch #1660500: hide iteration variable in list comps, add set comps and use common code to handle compilation of iterative expressions Modified: python/branches/p3yk/Misc/build.sh ============================================================================== --- python/branches/p3yk/Misc/build.sh (original) +++ python/branches/p3yk/Misc/build.sh Fri Apr 27 21:54:29 2007 @@ -47,6 +47,7 @@ FAILURE_SUBJECT="Python Regression Test Failures" #FAILURE_MAILTO="YOUR_ACCOUNT at gmail.com" FAILURE_MAILTO="python-checkins at python.org" +#FAILURE_CC="optional--uncomment and set to desired address" REMOTE_SYSTEM="neal at dinsdale.python.org" REMOTE_DIR="/data/ftp.python.org/pub/docs.python.org/dev/" @@ -91,7 +92,12 @@ mail_on_failure() { if [ "$NUM_FAILURES" != "0" ]; then - mutt -s "$FAILURE_SUBJECT $1 ($NUM_FAILURES)" $FAILURE_MAILTO < $2 + dest=$FAILURE_MAILTO + # FAILURE_CC is optional. + if [ "$FAILURE_CC" != "" ]; then + dest="$dest -c $FAILURE_CC" + fi + mutt -s "$FAILURE_SUBJECT $1 ($NUM_FAILURES)" $dest < $2 fi } @@ -208,8 +214,19 @@ cd $DIR/Doc F="make-doc.out" start=`current_time` -make >& ../build/$F -err=$? +# Doc/commontex/boilerplate.tex is expected to always have an outstanding +# modification for the date. When a release is cut, a conflict occurs. +# This allows us to detect this problem and not try to build the docs +# which will definitely fail with a conflict. +CONFLICTED_FILE=commontex/boilerplate.tex +conflict_count=`grep -c "<<<" $CONFLICTED_FILE` +if [ $conflict_count != 0 ]; then + echo "Conflict detected in $CONFLICTED_FILE. Doc build skipped." > ../build/$F + err=1 +else + make >& ../build/$F + err=$? +fi update_status "Making doc" "$F" $start if [ $err != 0 ]; then NUM_FAILURES=1 Modified: python/branches/p3yk/Misc/developers.txt ============================================================================== --- python/branches/p3yk/Misc/developers.txt (original) +++ python/branches/p3yk/Misc/developers.txt Fri Apr 27 21:54:29 2007 @@ -17,6 +17,18 @@ Permissions History ------------------- +- Travis Oliphant was given SVN access on 17 Apr 2007 by MvL, + for implementing the extended buffer protocol. + +- Ziga Seilnacht was given SVN access on 09 Mar 2007 by MvL, + for general maintenance. + +- Pete Shinners was given SVN access on 04 Mar 2007 by NCN, + for PEP 3101 work in the sandbox. + +- Pat Maupin and Eric V. Smith were given SVN access on 28 Feb 2007 by NCN, + for PEP 3101 work in the sandbox. + - Steven Bethard (SF name "bediviere") added to the SourceForge Python project 26 Feb 2007, by NCN, as a tracker tech. @@ -151,3 +163,4 @@ RDH: Raymond Hettinger TGP: Tim Peters DJG: David Goodger +MvL: Martin v. Loewis Modified: python/branches/p3yk/Misc/python-config.in ============================================================================== --- python/branches/p3yk/Misc/python-config.in (original) +++ python/branches/p3yk/Misc/python-config.in Fri Apr 27 21:54:29 2007 @@ -45,7 +45,9 @@ elif opt in ('--libs', '--ldflags'): libs = getvar('LIBS').split() + getvar('SYSLIBS').split() libs.append('-lpython'+pyver) - if opt == '--ldflags': + # add the prefix/lib/pythonX.Y/config dir, but only if there is no + # shared library in prefix/lib/. + if opt == '--ldflags' and not getvar('Py_ENABLE_SHARED'): libs.insert(0, '-L' + getvar('LIBPL')) print ' '.join(libs) Modified: python/branches/p3yk/Modules/_bsddb.c ============================================================================== --- python/branches/p3yk/Modules/_bsddb.c (original) +++ python/branches/p3yk/Modules/_bsddb.c Fri Apr 27 21:54:29 2007 @@ -749,6 +749,24 @@ Py_XDECREF(v); } + +/* The same, when the value is a time_t */ +static void _addTimeTToDict(PyObject* dict, char *name, time_t value) +{ + PyObject* v; + /* if the value fits in regular int, use that. */ +#ifdef HAVE_LONG_LONG + if (sizeof(time_t) > sizeof(long)) + v = PyLong_FromLongLong((PY_LONG_LONG) value); + else +#endif + v = PyInt_FromLong((long) value); + if (!v || PyDict_SetItemString(dict, name, v)) + PyErr_Clear(); + + Py_XDECREF(v); +} + #if (DBVER >= 43) /* add an db_seq_t to a dictionary using the given name as a key */ static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value) @@ -4633,8 +4651,9 @@ } #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) +#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name) - MAKE_ENTRY(time_ckp); + MAKE_TIME_T_ENTRY(time_ckp); MAKE_ENTRY(last_txnid); MAKE_ENTRY(maxtxns); MAKE_ENTRY(nactive); @@ -4647,6 +4666,7 @@ MAKE_ENTRY(region_nowait); #undef MAKE_ENTRY +#undef MAKE_TIME_T_ENTRY free(sp); return d; } Added: python/branches/p3yk/Modules/_collectionsmodule.c ============================================================================== --- (empty file) +++ python/branches/p3yk/Modules/_collectionsmodule.c Fri Apr 27 21:54:29 2007 @@ -0,0 +1,1370 @@ +#include "Python.h" +#include "structmember.h" + +/* collections module implementation of a deque() datatype + Written and maintained by Raymond D. Hettinger + Copyright (c) 2004 Python Software Foundation. + All rights reserved. +*/ + +/* The block length may be set to any number over 1. Larger numbers + * reduce the number of calls to the memory allocator but take more + * memory. Ideally, BLOCKLEN should be set with an eye to the + * length of a cache line. + */ + +#define BLOCKLEN 62 +#define CENTER ((BLOCKLEN - 1) / 2) + +/* A `dequeobject` is composed of a doubly-linked list of `block` nodes. + * This list is not circular (the leftmost block has leftlink==NULL, + * and the rightmost block has rightlink==NULL). A deque d's first + * element is at d.leftblock[leftindex] and its last element is at + * d.rightblock[rightindex]; note that, unlike as for Python slice + * indices, these indices are inclusive on both ends. By being inclusive + * on both ends, algorithms for left and right operations become + * symmetrical which simplifies the design. + * + * The list of blocks is never empty, so d.leftblock and d.rightblock + * are never equal to NULL. + * + * The indices, d.leftindex and d.rightindex are always in the range + * 0 <= index < BLOCKLEN. + * Their exact relationship is: + * (d.leftindex + d.len - 1) % BLOCKLEN == d.rightindex. + * + * Empty deques have d.len == 0; d.leftblock==d.rightblock; + * d.leftindex == CENTER+1; and d.rightindex == CENTER. + * Checking for d.len == 0 is the intended way to see whether d is empty. + * + * Whenever d.leftblock == d.rightblock, + * d.leftindex + d.len - 1 == d.rightindex. + * + * However, when d.leftblock != d.rightblock, d.leftindex and d.rightindex + * become indices into distinct blocks and either may be larger than the + * other. + */ + +typedef struct BLOCK { + struct BLOCK *leftlink; + struct BLOCK *rightlink; + PyObject *data[BLOCKLEN]; +} block; + +static block * +newblock(block *leftlink, block *rightlink, int len) { + block *b; + /* To prevent len from overflowing INT_MAX on 64-bit machines, we + * refuse to allocate new blocks if the current len is dangerously + * close. There is some extra margin to prevent spurious arithmetic + * overflows at various places. The following check ensures that + * the blocks allocated to the deque, in the worst case, can only + * have INT_MAX-2 entries in total. + */ + if (len >= INT_MAX - 2*BLOCKLEN) { + PyErr_SetString(PyExc_OverflowError, + "cannot add more blocks to the deque"); + return NULL; + } + b = PyMem_Malloc(sizeof(block)); + if (b == NULL) { + PyErr_NoMemory(); + return NULL; + } + b->leftlink = leftlink; + b->rightlink = rightlink; + return b; +} + +typedef struct { + PyObject_HEAD + block *leftblock; + block *rightblock; + int leftindex; /* in range(BLOCKLEN) */ + int rightindex; /* in range(BLOCKLEN) */ + int len; + long state; /* incremented whenever the indices move */ + PyObject *weakreflist; /* List of weak references */ +} dequeobject; + +static PyTypeObject deque_type; + +static PyObject * +deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + dequeobject *deque; + block *b; + + if (type == &deque_type && !_PyArg_NoKeywords("deque()", kwds)) + return NULL; + + /* create dequeobject structure */ + deque = (dequeobject *)type->tp_alloc(type, 0); + if (deque == NULL) + return NULL; + + b = newblock(NULL, NULL, 0); + if (b == NULL) { + Py_DECREF(deque); + return NULL; + } + + assert(BLOCKLEN >= 2); + deque->leftblock = b; + deque->rightblock = b; + deque->leftindex = CENTER + 1; + deque->rightindex = CENTER; + deque->len = 0; + deque->state = 0; + deque->weakreflist = NULL; + + return (PyObject *)deque; +} + +static PyObject * +deque_append(dequeobject *deque, PyObject *item) +{ + deque->state++; + if (deque->rightindex == BLOCKLEN-1) { + block *b = newblock(deque->rightblock, NULL, deque->len); + if (b == NULL) + return NULL; + assert(deque->rightblock->rightlink == NULL); + deque->rightblock->rightlink = b; + deque->rightblock = b; + deque->rightindex = -1; + } + Py_INCREF(item); + deque->len++; + deque->rightindex++; + deque->rightblock->data[deque->rightindex] = item; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(append_doc, "Add an element to the right side of the deque."); + +static PyObject * +deque_appendleft(dequeobject *deque, PyObject *item) +{ + deque->state++; + if (deque->leftindex == 0) { + block *b = newblock(NULL, deque->leftblock, deque->len); + if (b == NULL) + return NULL; + assert(deque->leftblock->leftlink == NULL); + deque->leftblock->leftlink = b; + deque->leftblock = b; + deque->leftindex = BLOCKLEN; + } + Py_INCREF(item); + deque->len++; + deque->leftindex--; + deque->leftblock->data[deque->leftindex] = item; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(appendleft_doc, "Add an element to the left side of the deque."); + +static PyObject * +deque_pop(dequeobject *deque, PyObject *unused) +{ + PyObject *item; + block *prevblock; + + if (deque->len == 0) { + PyErr_SetString(PyExc_IndexError, "pop from an empty deque"); + return NULL; + } + item = deque->rightblock->data[deque->rightindex]; + deque->rightindex--; + deque->len--; + deque->state++; + + if (deque->rightindex == -1) { + if (deque->len == 0) { + assert(deque->leftblock == deque->rightblock); + assert(deque->leftindex == deque->rightindex+1); + /* re-center instead of freeing a block */ + deque->leftindex = CENTER + 1; + deque->rightindex = CENTER; + } else { + prevblock = deque->rightblock->leftlink; + assert(deque->leftblock != deque->rightblock); + PyMem_Free(deque->rightblock); + prevblock->rightlink = NULL; + deque->rightblock = prevblock; + deque->rightindex = BLOCKLEN - 1; + } + } + return item; +} + +PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element."); + +static PyObject * +deque_popleft(dequeobject *deque, PyObject *unused) +{ + PyObject *item; + block *prevblock; + + if (deque->len == 0) { + PyErr_SetString(PyExc_IndexError, "pop from an empty deque"); + return NULL; + } + assert(deque->leftblock != NULL); + item = deque->leftblock->data[deque->leftindex]; + deque->leftindex++; + deque->len--; + deque->state++; + + if (deque->leftindex == BLOCKLEN) { + if (deque->len == 0) { + assert(deque->leftblock == deque->rightblock); + assert(deque->leftindex == deque->rightindex+1); + /* re-center instead of freeing a block */ + deque->leftindex = CENTER + 1; + deque->rightindex = CENTER; + } else { + assert(deque->leftblock != deque->rightblock); + prevblock = deque->leftblock->rightlink; + PyMem_Free(deque->leftblock); + assert(prevblock != NULL); + prevblock->leftlink = NULL; + deque->leftblock = prevblock; + deque->leftindex = 0; + } + } + return item; +} + +PyDoc_STRVAR(popleft_doc, "Remove and return the leftmost element."); + +static PyObject * +deque_extend(dequeobject *deque, PyObject *iterable) +{ + PyObject *it, *item; + + it = PyObject_GetIter(iterable); + if (it == NULL) + return NULL; + + while ((item = PyIter_Next(it)) != NULL) { + deque->state++; + if (deque->rightindex == BLOCKLEN-1) { + block *b = newblock(deque->rightblock, NULL, + deque->len); + if (b == NULL) { + Py_DECREF(item); + Py_DECREF(it); + return NULL; + } + assert(deque->rightblock->rightlink == NULL); + deque->rightblock->rightlink = b; + deque->rightblock = b; + deque->rightindex = -1; + } + deque->len++; + deque->rightindex++; + deque->rightblock->data[deque->rightindex] = item; + } + Py_DECREF(it); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(extend_doc, +"Extend the right side of the deque with elements from the iterable"); + +static PyObject * +deque_extendleft(dequeobject *deque, PyObject *iterable) +{ + PyObject *it, *item; + + it = PyObject_GetIter(iterable); + if (it == NULL) + return NULL; + + while ((item = PyIter_Next(it)) != NULL) { + deque->state++; + if (deque->leftindex == 0) { + block *b = newblock(NULL, deque->leftblock, + deque->len); + if (b == NULL) { + Py_DECREF(item); + Py_DECREF(it); + return NULL; + } + assert(deque->leftblock->leftlink == NULL); + deque->leftblock->leftlink = b; + deque->leftblock = b; + deque->leftindex = BLOCKLEN; + } + deque->len++; + deque->leftindex--; + deque->leftblock->data[deque->leftindex] = item; + } + Py_DECREF(it); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(extendleft_doc, +"Extend the left side of the deque with elements from the iterable"); + +static int +_deque_rotate(dequeobject *deque, Py_ssize_t n) +{ + int i, len=deque->len, halflen=(len+1)>>1; + PyObject *item, *rv; + + if (len == 0) + return 0; + if (n > halflen || n < -halflen) { + n %= len; + if (n > halflen) + n -= len; + else if (n < -halflen) + n += len; + } + + for (i=0 ; in ; i--) { + item = deque_popleft(deque, NULL); + assert (item != NULL); + rv = deque_append(deque, item); + Py_DECREF(item); + if (rv == NULL) + return -1; + Py_DECREF(rv); + } + return 0; +} + +static PyObject * +deque_rotate(dequeobject *deque, PyObject *args) +{ + int n=1; + + if (!PyArg_ParseTuple(args, "|i:rotate", &n)) + return NULL; + if (_deque_rotate(deque, n) == 0) + Py_RETURN_NONE; + return NULL; +} + +PyDoc_STRVAR(rotate_doc, +"Rotate the deque n steps to the right (default n=1). If n is negative, rotates left."); + +static Py_ssize_t +deque_len(dequeobject *deque) +{ + return deque->len; +} + +static PyObject * +deque_remove(dequeobject *deque, PyObject *value) +{ + Py_ssize_t i, n=deque->len; + + for (i=0 ; ileftblock->data[deque->leftindex]; + int cmp = PyObject_RichCompareBool(item, value, Py_EQ); + + if (deque->len != n) { + PyErr_SetString(PyExc_IndexError, + "deque mutated during remove()."); + return NULL; + } + if (cmp > 0) { + PyObject *tgt = deque_popleft(deque, NULL); + assert (tgt != NULL); + Py_DECREF(tgt); + if (_deque_rotate(deque, i) == -1) + return NULL; + Py_RETURN_NONE; + } + else if (cmp < 0) { + _deque_rotate(deque, i); + return NULL; + } + _deque_rotate(deque, -1); + } + PyErr_SetString(PyExc_ValueError, "deque.remove(x): x not in deque"); + return NULL; +} + +PyDoc_STRVAR(remove_doc, +"D.remove(value) -- remove first occurrence of value."); + +static int +deque_clear(dequeobject *deque) +{ + PyObject *item; + + while (deque->len) { + item = deque_pop(deque, NULL); + assert (item != NULL); + Py_DECREF(item); + } + assert(deque->leftblock == deque->rightblock && + deque->leftindex - 1 == deque->rightindex && + deque->len == 0); + return 0; +} + +static PyObject * +deque_item(dequeobject *deque, int i) +{ + block *b; + PyObject *item; + int n, index=i; + + if (i < 0 || i >= deque->len) { + PyErr_SetString(PyExc_IndexError, + "deque index out of range"); + return NULL; + } + + if (i == 0) { + i = deque->leftindex; + b = deque->leftblock; + } else if (i == deque->len - 1) { + i = deque->rightindex; + b = deque->rightblock; + } else { + i += deque->leftindex; + n = i / BLOCKLEN; + i %= BLOCKLEN; + if (index < (deque->len >> 1)) { + b = deque->leftblock; + while (n--) + b = b->rightlink; + } else { + n = (deque->leftindex + deque->len - 1) / BLOCKLEN - n; + b = deque->rightblock; + while (n--) + b = b->leftlink; + } + } + item = b->data[i]; + Py_INCREF(item); + return item; +} + +/* delitem() implemented in terms of rotate for simplicity and reasonable + performance near the end points. If for some reason this method becomes + popular, it is not hard to re-implement this using direct data movement + (similar to code in list slice assignment) and achieve a two or threefold + performance boost. +*/ + +static int +deque_del_item(dequeobject *deque, Py_ssize_t i) +{ + PyObject *item; + + assert (i >= 0 && i < deque->len); + if (_deque_rotate(deque, -i) == -1) + return -1; + + item = deque_popleft(deque, NULL); + assert (item != NULL); + Py_DECREF(item); + + return _deque_rotate(deque, i); +} + +static int +deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v) +{ + PyObject *old_value; + block *b; + Py_ssize_t n, len=deque->len, halflen=(len+1)>>1, index=i; + + if (i < 0 || i >= len) { + PyErr_SetString(PyExc_IndexError, + "deque index out of range"); + return -1; + } + if (v == NULL) + return deque_del_item(deque, i); + + i += deque->leftindex; + n = i / BLOCKLEN; + i %= BLOCKLEN; + if (index <= halflen) { + b = deque->leftblock; + while (n--) + b = b->rightlink; + } else { + n = (deque->leftindex + len - 1) / BLOCKLEN - n; + b = deque->rightblock; + while (n--) + b = b->leftlink; + } + Py_INCREF(v); + old_value = b->data[i]; + b->data[i] = v; + Py_DECREF(old_value); + return 0; +} + +static PyObject * +deque_clearmethod(dequeobject *deque) +{ + int rv; + + rv = deque_clear(deque); + assert (rv != -1); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(clear_doc, "Remove all elements from the deque."); + +static void +deque_dealloc(dequeobject *deque) +{ + PyObject_GC_UnTrack(deque); + if (deque->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) deque); + if (deque->leftblock != NULL) { + deque_clear(deque); + assert(deque->leftblock != NULL); + PyMem_Free(deque->leftblock); + } + deque->leftblock = NULL; + deque->rightblock = NULL; + deque->ob_type->tp_free(deque); +} + +static int +deque_traverse(dequeobject *deque, visitproc visit, void *arg) +{ + block *b; + PyObject *item; + int index; + int indexlo = deque->leftindex; + + for (b = deque->leftblock; b != NULL; b = b->rightlink) { + const int indexhi = b == deque->rightblock ? + deque->rightindex : + BLOCKLEN - 1; + + for (index = indexlo; index <= indexhi; ++index) { + item = b->data[index]; + Py_VISIT(item); + } + indexlo = 0; + } + return 0; +} + +static long +deque_nohash(PyObject *self) +{ + PyErr_SetString(PyExc_TypeError, "deque objects are unhashable"); + return -1; +} + +static PyObject * +deque_copy(PyObject *deque) +{ + return PyObject_CallFunctionObjArgs((PyObject *)(deque->ob_type), + deque, NULL); +} + +PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque."); + +static PyObject * +deque_reduce(dequeobject *deque) +{ + PyObject *dict, *result, *it; + + dict = PyObject_GetAttrString((PyObject *)deque, "__dict__"); + if (dict == NULL) { + PyErr_Clear(); + dict = Py_None; + Py_INCREF(dict); + } + it = PyObject_GetIter((PyObject *)deque); + if (it == NULL) { + Py_DECREF(dict); + return NULL; + } + result = Py_BuildValue("O()ON", deque->ob_type, dict, it); + Py_DECREF(dict); + return result; +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +deque_repr(PyObject *deque) +{ + PyObject *aslist, *result, *fmt; + int i; + + i = Py_ReprEnter(deque); + if (i != 0) { + if (i < 0) + return NULL; + return PyString_FromString("[...]"); + } + + aslist = PySequence_List(deque); + if (aslist == NULL) { + Py_ReprLeave(deque); + return NULL; + } + + fmt = PyString_FromString("deque(%r)"); + if (fmt == NULL) { + Py_DECREF(aslist); + Py_ReprLeave(deque); + return NULL; + } + result = PyString_Format(fmt, aslist); + Py_DECREF(fmt); + Py_DECREF(aslist); + Py_ReprLeave(deque); + return result; +} + +static int +deque_tp_print(PyObject *deque, FILE *fp, int flags) +{ + PyObject *it, *item; + char *emit = ""; /* No separator emitted on first pass */ + char *separator = ", "; + int i; + + i = Py_ReprEnter(deque); + if (i != 0) { + if (i < 0) + return i; + fputs("[...]", fp); + return 0; + } + + it = PyObject_GetIter(deque); + if (it == NULL) + return -1; + + fputs("deque([", fp); + while ((item = PyIter_Next(it)) != NULL) { + fputs(emit, fp); + emit = separator; + if (PyObject_Print(item, fp, 0) != 0) { + Py_DECREF(item); + Py_DECREF(it); + Py_ReprLeave(deque); + return -1; + } + Py_DECREF(item); + } + Py_ReprLeave(deque); + Py_DECREF(it); + if (PyErr_Occurred()) + return -1; + fputs("])", fp); + return 0; +} + +static PyObject * +deque_richcompare(PyObject *v, PyObject *w, int op) +{ + PyObject *it1=NULL, *it2=NULL, *x, *y; + int b, vs, ws, cmp=-1; + + if (!PyObject_TypeCheck(v, &deque_type) || + !PyObject_TypeCheck(w, &deque_type)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + /* Shortcuts */ + vs = ((dequeobject *)v)->len; + ws = ((dequeobject *)w)->len; + if (op == Py_EQ) { + if (v == w) + Py_RETURN_TRUE; + if (vs != ws) + Py_RETURN_FALSE; + } + if (op == Py_NE) { + if (v == w) + Py_RETURN_FALSE; + if (vs != ws) + Py_RETURN_TRUE; + } + + /* Search for the first index where items are different */ + it1 = PyObject_GetIter(v); + if (it1 == NULL) + goto done; + it2 = PyObject_GetIter(w); + if (it2 == NULL) + goto done; + for (;;) { + x = PyIter_Next(it1); + if (x == NULL && PyErr_Occurred()) + goto done; + y = PyIter_Next(it2); + if (x == NULL || y == NULL) + break; + b = PyObject_RichCompareBool(x, y, Py_EQ); + if (b == 0) { + cmp = PyObject_RichCompareBool(x, y, op); + Py_DECREF(x); + Py_DECREF(y); + goto done; + } + Py_DECREF(x); + Py_DECREF(y); + if (b == -1) + goto done; + } + /* We reached the end of one deque or both */ + Py_XDECREF(x); + Py_XDECREF(y); + if (PyErr_Occurred()) + goto done; + switch (op) { + case Py_LT: cmp = y != NULL; break; /* if w was longer */ + case Py_LE: cmp = x == NULL; break; /* if v was not longer */ + case Py_EQ: cmp = x == y; break; /* if we reached the end of both */ + case Py_NE: cmp = x != y; break; /* if one deque continues */ + case Py_GT: cmp = x != NULL; break; /* if v was longer */ + case Py_GE: cmp = y == NULL; break; /* if w was not longer */ + } + +done: + Py_XDECREF(it1); + Py_XDECREF(it2); + if (cmp == 1) + Py_RETURN_TRUE; + if (cmp == 0) + Py_RETURN_FALSE; + return NULL; +} + +static int +deque_init(dequeobject *deque, PyObject *args, PyObject *kwds) +{ + PyObject *iterable = NULL; + + if (!PyArg_UnpackTuple(args, "deque", 0, 1, &iterable)) + return -1; + + if (iterable != NULL) { + PyObject *rv = deque_extend(deque, iterable); + if (rv == NULL) + return -1; + Py_DECREF(rv); + } + return 0; +} + +static PySequenceMethods deque_as_sequence = { + (lenfunc)deque_len, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + (ssizeargfunc)deque_item, /* sq_item */ + 0, /* sq_slice */ + (ssizeobjargproc)deque_ass_item, /* sq_ass_item */ +}; + +/* deque object ********************************************************/ + +static PyObject *deque_iter(dequeobject *deque); +static PyObject *deque_reviter(dequeobject *deque); +PyDoc_STRVAR(reversed_doc, + "D.__reversed__() -- return a reverse iterator over the deque"); + +static PyMethodDef deque_methods[] = { + {"append", (PyCFunction)deque_append, + METH_O, append_doc}, + {"appendleft", (PyCFunction)deque_appendleft, + METH_O, appendleft_doc}, + {"clear", (PyCFunction)deque_clearmethod, + METH_NOARGS, clear_doc}, + {"__copy__", (PyCFunction)deque_copy, + METH_NOARGS, copy_doc}, + {"extend", (PyCFunction)deque_extend, + METH_O, extend_doc}, + {"extendleft", (PyCFunction)deque_extendleft, + METH_O, extendleft_doc}, + {"pop", (PyCFunction)deque_pop, + METH_NOARGS, pop_doc}, + {"popleft", (PyCFunction)deque_popleft, + METH_NOARGS, popleft_doc}, + {"__reduce__", (PyCFunction)deque_reduce, + METH_NOARGS, reduce_doc}, + {"remove", (PyCFunction)deque_remove, + METH_O, remove_doc}, + {"__reversed__", (PyCFunction)deque_reviter, + METH_NOARGS, reversed_doc}, + {"rotate", (PyCFunction)deque_rotate, + METH_VARARGS, rotate_doc}, + {NULL, NULL} /* sentinel */ +}; + +PyDoc_STRVAR(deque_doc, +"deque(iterable) --> deque object\n\ +\n\ +Build an ordered collection accessible from endpoints only."); + +static PyTypeObject deque_type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "collections.deque", /* tp_name */ + sizeof(dequeobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)deque_dealloc, /* tp_dealloc */ + deque_tp_print, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + deque_repr, /* tp_repr */ + 0, /* tp_as_number */ + &deque_as_sequence, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + deque_nohash, /* 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 | Py_TPFLAGS_HAVE_GC, + /* tp_flags */ + deque_doc, /* tp_doc */ + (traverseproc)deque_traverse, /* tp_traverse */ + (inquiry)deque_clear, /* tp_clear */ + (richcmpfunc)deque_richcompare, /* tp_richcompare */ + offsetof(dequeobject, weakreflist), /* tp_weaklistoffset*/ + (getiterfunc)deque_iter, /* tp_iter */ + 0, /* tp_iternext */ + deque_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 */ + (initproc)deque_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + deque_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + +/*********************** Deque Iterator **************************/ + +typedef struct { + PyObject_HEAD + int index; + block *b; + dequeobject *deque; + long state; /* state when the iterator is created */ + int counter; /* number of items remaining for iteration */ +} dequeiterobject; + +PyTypeObject dequeiter_type; + +static PyObject * +deque_iter(dequeobject *deque) +{ + dequeiterobject *it; + + it = PyObject_New(dequeiterobject, &dequeiter_type); + if (it == NULL) + return NULL; + it->b = deque->leftblock; + it->index = deque->leftindex; + Py_INCREF(deque); + it->deque = deque; + it->state = deque->state; + it->counter = deque->len; + return (PyObject *)it; +} + +static void +dequeiter_dealloc(dequeiterobject *dio) +{ + Py_XDECREF(dio->deque); + dio->ob_type->tp_free(dio); +} + +static PyObject * +dequeiter_next(dequeiterobject *it) +{ + PyObject *item; + + if (it->deque->state != it->state) { + it->counter = 0; + PyErr_SetString(PyExc_RuntimeError, + "deque mutated during iteration"); + return NULL; + } + if (it->counter == 0) + return NULL; + assert (!(it->b == it->deque->rightblock && + it->index > it->deque->rightindex)); + + item = it->b->data[it->index]; + it->index++; + it->counter--; + if (it->index == BLOCKLEN && it->counter > 0) { + assert (it->b->rightlink != NULL); + it->b = it->b->rightlink; + it->index = 0; + } + Py_INCREF(item); + return item; +} + +static PyObject * +dequeiter_len(dequeiterobject *it) +{ + return PyInt_FromLong(it->counter); +} + +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); + +static PyMethodDef dequeiter_methods[] = { + {"__length_hint__", (PyCFunction)dequeiter_len, METH_NOARGS, length_hint_doc}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject dequeiter_type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "deque_iterator", /* tp_name */ + sizeof(dequeiterobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)dequeiter_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* 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, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)dequeiter_next, /* tp_iternext */ + dequeiter_methods, /* tp_methods */ + 0, +}; + +/*********************** Deque Reverse Iterator **************************/ + +PyTypeObject dequereviter_type; + +static PyObject * +deque_reviter(dequeobject *deque) +{ + dequeiterobject *it; + + it = PyObject_New(dequeiterobject, &dequereviter_type); + if (it == NULL) + return NULL; + it->b = deque->rightblock; + it->index = deque->rightindex; + Py_INCREF(deque); + it->deque = deque; + it->state = deque->state; + it->counter = deque->len; + return (PyObject *)it; +} + +static PyObject * +dequereviter_next(dequeiterobject *it) +{ + PyObject *item; + if (it->counter == 0) + return NULL; + + if (it->deque->state != it->state) { + it->counter = 0; + PyErr_SetString(PyExc_RuntimeError, + "deque mutated during iteration"); + return NULL; + } + assert (!(it->b == it->deque->leftblock && + it->index < it->deque->leftindex)); + + item = it->b->data[it->index]; + it->index--; + it->counter--; + if (it->index == -1 && it->counter > 0) { + assert (it->b->leftlink != NULL); + it->b = it->b->leftlink; + it->index = BLOCKLEN - 1; + } + Py_INCREF(item); + return item; +} + +PyTypeObject dequereviter_type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "deque_reverse_iterator", /* tp_name */ + sizeof(dequeiterobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)dequeiter_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* 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, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)dequereviter_next, /* tp_iternext */ + dequeiter_methods, /* tp_methods */ + 0, +}; + +/* defaultdict type *********************************************************/ + +typedef struct { + PyDictObject dict; + PyObject *default_factory; +} defdictobject; + +static PyTypeObject defdict_type; /* Forward */ + +PyDoc_STRVAR(defdict_missing_doc, +"__missing__(key) # Called by __getitem__ for missing key; pseudo-code:\n\ + if self.default_factory is None: raise KeyError((key,))\n\ + self[key] = value = self.default_factory()\n\ + return value\n\ +"); + +static PyObject * +defdict_missing(defdictobject *dd, PyObject *key) +{ + PyObject *factory = dd->default_factory; + PyObject *value; + if (factory == NULL || factory == Py_None) { + /* XXX Call dict.__missing__(key) */ + PyObject *tup; + tup = PyTuple_Pack(1, key); + if (!tup) return NULL; + PyErr_SetObject(PyExc_KeyError, tup); + Py_DECREF(tup); + return NULL; + } + value = PyEval_CallObject(factory, NULL); + if (value == NULL) + return value; + if (PyObject_SetItem((PyObject *)dd, key, value) < 0) { + Py_DECREF(value); + return NULL; + } + return value; +} + +PyDoc_STRVAR(defdict_copy_doc, "D.copy() -> a shallow copy of D."); + +static PyObject * +defdict_copy(defdictobject *dd) +{ + /* This calls the object's class. That only works for subclasses + whose class constructor has the same signature. Subclasses that + define a different constructor signature must override copy(). + */ + return PyObject_CallFunctionObjArgs((PyObject *)dd->dict.ob_type, + dd->default_factory, dd, NULL); +} + +static PyObject * +defdict_reduce(defdictobject *dd) +{ + /* __reduce__ must return a 5-tuple as follows: + + - factory function + - tuple of args for the factory function + - additional state (here None) + - sequence iterator (here None) + - dictionary iterator (yielding successive (key, value) pairs + + This API is used by pickle.py and copy.py. + + For this to be useful with pickle.py, the default_factory + must be picklable; e.g., None, a built-in, or a global + function in a module or package. + + Both shallow and deep copying are supported, but for deep + copying, the default_factory must be deep-copyable; e.g. None, + or a built-in (functions are not copyable at this time). + + This only works for subclasses as long as their constructor + signature is compatible; the first argument must be the + optional default_factory, defaulting to None. + */ + PyObject *args; + PyObject *items; + PyObject *result; + if (dd->default_factory == NULL || dd->default_factory == Py_None) + args = PyTuple_New(0); + else + args = PyTuple_Pack(1, dd->default_factory); + if (args == NULL) + return NULL; + items = PyObject_CallMethod((PyObject *)dd, "items", "()"); + if (items == NULL) { + Py_DECREF(args); + return NULL; + } + result = PyTuple_Pack(5, dd->dict.ob_type, args, + Py_None, Py_None, items); + Py_DECREF(items); + Py_DECREF(args); + return result; +} + +static PyMethodDef defdict_methods[] = { + {"__missing__", (PyCFunction)defdict_missing, METH_O, + defdict_missing_doc}, + {"copy", (PyCFunction)defdict_copy, METH_NOARGS, + defdict_copy_doc}, + {"__copy__", (PyCFunction)defdict_copy, METH_NOARGS, + defdict_copy_doc}, + {"__reduce__", (PyCFunction)defdict_reduce, METH_NOARGS, + reduce_doc}, + {NULL} +}; + +static PyMemberDef defdict_members[] = { + {"default_factory", T_OBJECT, + offsetof(defdictobject, default_factory), 0, + PyDoc_STR("Factory for default value called by __missing__().")}, + {NULL} +}; + +static void +defdict_dealloc(defdictobject *dd) +{ + Py_CLEAR(dd->default_factory); + PyDict_Type.tp_dealloc((PyObject *)dd); +} + +static int +defdict_print(defdictobject *dd, FILE *fp, int flags) +{ + int sts; + fprintf(fp, "defaultdict("); + if (dd->default_factory == NULL) + fprintf(fp, "None"); + else { + PyObject_Print(dd->default_factory, fp, 0); + } + fprintf(fp, ", "); + sts = PyDict_Type.tp_print((PyObject *)dd, fp, 0); + fprintf(fp, ")"); + return sts; +} + +static PyObject * +defdict_repr(defdictobject *dd) +{ + PyObject *defrepr; + PyObject *baserepr; + PyObject *result; + baserepr = PyDict_Type.tp_repr((PyObject *)dd); + if (baserepr == NULL) + return NULL; + if (dd->default_factory == NULL) + defrepr = PyString_FromString("None"); + else + defrepr = PyObject_Repr(dd->default_factory); + if (defrepr == NULL) { + Py_DECREF(baserepr); + return NULL; + } + result = PyString_FromFormat("defaultdict(%s, %s)", + PyString_AS_STRING(defrepr), + PyString_AS_STRING(baserepr)); + Py_DECREF(defrepr); + Py_DECREF(baserepr); + return result; +} + +static int +defdict_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(((defdictobject *)self)->default_factory); + return PyDict_Type.tp_traverse(self, visit, arg); +} + +static int +defdict_tp_clear(defdictobject *dd) +{ + Py_CLEAR(dd->default_factory); + return PyDict_Type.tp_clear((PyObject *)dd); +} + +static int +defdict_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + defdictobject *dd = (defdictobject *)self; + PyObject *olddefault = dd->default_factory; + PyObject *newdefault = NULL; + PyObject *newargs; + int result; + if (args == NULL || !PyTuple_Check(args)) + newargs = PyTuple_New(0); + else { + Py_ssize_t n = PyTuple_GET_SIZE(args); + if (n > 0) { + newdefault = PyTuple_GET_ITEM(args, 0); + if (!PyCallable_Check(newdefault)) { + PyErr_SetString(PyExc_TypeError, + "first argument must be callable"); + return -1; + } + } + newargs = PySequence_GetSlice(args, 1, n); + } + if (newargs == NULL) + return -1; + Py_XINCREF(newdefault); + dd->default_factory = newdefault; + result = PyDict_Type.tp_init(self, newargs, kwds); + Py_DECREF(newargs); + Py_XDECREF(olddefault); + return result; +} + +PyDoc_STRVAR(defdict_doc, +"defaultdict(default_factory) --> dict with default factory\n\ +\n\ +The default factory is called without arguments to produce\n\ +a new value when a key is not present, in __getitem__ only.\n\ +A defaultdict compares equal to a dict with the same items.\n\ +"); + +/* See comment in xxsubtype.c */ +#define DEFERRED_ADDRESS(ADDR) 0 + +static PyTypeObject defdict_type = { + PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) + 0, /* ob_size */ + "collections.defaultdict", /* tp_name */ + sizeof(defdictobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)defdict_dealloc, /* tp_dealloc */ + (printfunc)defdict_print, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)defdict_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 | Py_TPFLAGS_HAVE_GC, + /* tp_flags */ + defdict_doc, /* tp_doc */ + defdict_traverse, /* tp_traverse */ + (inquiry)defdict_tp_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset*/ + 0, /* tp_iter */ + 0, /* tp_iternext */ + defdict_methods, /* tp_methods */ + defdict_members, /* tp_members */ + 0, /* tp_getset */ + DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + defdict_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + 0, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + +/* module level code ********************************************************/ + +PyDoc_STRVAR(module_doc, +"High performance data structures.\n\ +- deque: ordered collection accessible from endpoints only\n\ +- defaultdict: dict subclass with a default value factory\n\ +"); + +PyMODINIT_FUNC +init_collections(void) +{ + PyObject *m; + + m = Py_InitModule3("_collections", NULL, module_doc); + if (m == NULL) + return; + + if (PyType_Ready(&deque_type) < 0) + return; + Py_INCREF(&deque_type); + PyModule_AddObject(m, "deque", (PyObject *)&deque_type); + + defdict_type.tp_base = &PyDict_Type; + if (PyType_Ready(&defdict_type) < 0) + return; + Py_INCREF(&defdict_type); + PyModule_AddObject(m, "defaultdict", (PyObject *)&defdict_type); + + if (PyType_Ready(&dequeiter_type) < 0) + return; + + if (PyType_Ready(&dequereviter_type) < 0) + return; + + return; +} Modified: python/branches/p3yk/Modules/_ctypes/_ctypes.c ============================================================================== --- python/branches/p3yk/Modules/_ctypes/_ctypes.c (original) +++ python/branches/p3yk/Modules/_ctypes/_ctypes.c Fri Apr 27 21:54:29 2007 @@ -339,24 +339,6 @@ ((PyTypeObject *)type)->tp_name, ob_name); return NULL; } -#if 1 -/* XXX Remove this section ??? */ - /* tuple returned by byref: */ - /* ('i', addr, obj) */ - if (PyTuple_Check(value)) { - PyObject *ob; - StgDictObject *dict; - - dict = PyType_stgdict(type); - ob = PyTuple_GetItem(value, 2); - if (dict && ob && - 0 == PyObject_IsInstance(value, dict->proto)) { - Py_INCREF(value); - return value; - } - } -/* ... and leave the rest */ -#endif as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); if (as_parameter) { @@ -1020,6 +1002,12 @@ } itemsize = itemdict->size; + if (length * itemsize < 0) { + PyErr_SetString(PyExc_OverflowError, + "array too large"); + return NULL; + } + itemalign = itemdict->align; stgdict->size = itemsize * length; @@ -1119,7 +1107,7 @@ */ -static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv"; +static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvt"; static PyObject * c_wchar_p_from_param(PyObject *type, PyObject *value) @@ -2194,21 +2182,32 @@ 0, /* tp_free */ }; -static void CData_MallocBuffer(CDataObject *obj, StgDictObject *dict) +static int CData_MallocBuffer(CDataObject *obj, StgDictObject *dict) { if ((size_t)dict->size <= sizeof(obj->b_value)) { /* No need to call malloc, can use the default buffer */ obj->b_ptr = (char *)&obj->b_value; + /* The b_needsfree flag does not mean that we actually did + call PyMem_Malloc to allocate the memory block; instead it + means we are the *owner* of the memory and are responsible + for freeing resources associated with the memory. This is + also the reason that b_needsfree is exposed to Python. + */ obj->b_needsfree = 1; } else { /* In python 2.4, and ctypes 0.9.6, the malloc call took about 33% of the creation time for c_int(). */ obj->b_ptr = (char *)PyMem_Malloc(dict->size); + if (obj->b_ptr == NULL) { + PyErr_NoMemory(); + return -1; + } obj->b_needsfree = 1; memset(obj->b_ptr, 0, dict->size); } obj->b_size = dict->size; + return 0; } PyObject * @@ -2240,7 +2239,10 @@ cmem->b_base = (CDataObject *)base; cmem->b_index = index; } else { /* copy contents of adr */ - CData_MallocBuffer(cmem, dict); + if (-1 == CData_MallocBuffer(cmem, dict)) { + return NULL; + Py_DECREF(cmem); + } memcpy(cmem->b_ptr, adr, dict->size); cmem->b_index = index; } @@ -2453,7 +2455,10 @@ obj->b_objects = NULL; obj->b_length = dict->length; - CData_MallocBuffer(obj, dict); + if (-1 == CData_MallocBuffer(obj, dict)) { + Py_DECREF(obj); + return NULL; + } return (PyObject *)obj; } /*****************************************************************/ @@ -4535,9 +4540,9 @@ #endif static PyObject * -string_at(const char *ptr, Py_ssize_t size) +string_at(const char *ptr, int size) { - if (size == 0) + if (size == -1) return PyString_FromString(ptr); return PyString_FromStringAndSize(ptr, size); } @@ -4622,7 +4627,7 @@ static PyObject * wstring_at(const wchar_t *ptr, int size) { - if (size == 0) + if (size == -1) size = wcslen(ptr); return PyUnicode_FromWideChar(ptr, size); } Modified: python/branches/p3yk/Modules/_ctypes/callproc.c ============================================================================== --- python/branches/p3yk/Modules/_ctypes/callproc.c (original) +++ python/branches/p3yk/Modules/_ctypes/callproc.c Fri Apr 27 21:54:29 2007 @@ -64,6 +64,7 @@ #ifdef MS_WIN32 #include +#include #else #include "ctypes_dlfcn.h" #endif @@ -97,9 +98,9 @@ 0, NULL); if (n) { - while (isspace(lpMsgBuf[n-1])) + while (_istspace(lpMsgBuf[n-1])) --n; - lpMsgBuf[n] = '\0'; /* rstrip() */ + lpMsgBuf[n] = _T('\0'); /* rstrip() */ } return lpMsgBuf; } Modified: python/branches/p3yk/Modules/_ctypes/cfield.c ============================================================================== --- python/branches/p3yk/Modules/_ctypes/cfield.c (original) +++ python/branches/p3yk/Modules/_ctypes/cfield.c Fri Apr 27 21:54:29 2007 @@ -725,6 +725,35 @@ } #endif +#ifdef HAVE_C99_BOOL +#define BOOL_TYPE _Bool +#else +#define BOOL_TYPE char +#undef SIZEOF__BOOL +#define SIZEOF__BOOL 1 +#endif + +static PyObject * +t_set(void *ptr, PyObject *value, unsigned size) +{ + switch (PyObject_IsTrue(value)) { + case -1: + return NULL; + case 0: + *(BOOL_TYPE *)ptr = 0; + _RET(value); + default: + *(BOOL_TYPE *)ptr = 1; + _RET(value); + } +} + +static PyObject * +t_get(void *ptr, unsigned size) +{ + return PyBool_FromLong((long)*(BOOL_TYPE *)ptr); +} + static PyObject * I_set(void *ptr, PyObject *value, unsigned size) { @@ -1432,19 +1461,10 @@ #endif #ifdef MS_WIN32 -/* We cannot use SysFreeString as the PyCObject_FromVoidPtr - because of different calling convention -*/ -static void _my_SysFreeString(void *p) -{ - SysFreeString((BSTR)p); -} - static PyObject * BSTR_set(void *ptr, PyObject *value, unsigned size) { BSTR bstr; - PyObject *result; /* convert value into a PyUnicodeObject or NULL */ if (Py_None == value) { @@ -1472,19 +1492,15 @@ } else bstr = NULL; - if (bstr) { - result = PyCObject_FromVoidPtr((void *)bstr, _my_SysFreeString); - if (result == NULL) { - SysFreeString(bstr); - return NULL; - } - } else { - result = Py_None; - Py_INCREF(result); - } - + /* free the previous contents, if any */ + if (*(BSTR *)ptr) + SysFreeString(*(BSTR *)ptr); + + /* and store it */ *(BSTR *)ptr = bstr; - return result; + + /* We don't need to keep any other object */ + _RET(value); } @@ -1585,6 +1601,17 @@ { 'X', BSTR_set, BSTR_get, &ffi_type_pointer}, { 'v', vBOOL_set, vBOOL_get, &ffi_type_sshort}, #endif +#if SIZEOF__BOOL == 1 + { 't', t_set, t_get, &ffi_type_uchar}, /* Also fallback for no native _Bool support */ +#elif SIZEOF__BOOL == SIZEOF_SHORT + { 't', t_set, t_get, &ffi_type_ushort}, +#elif SIZEOF__BOOL == SIZEOF_INT + { 't', t_set, t_get, &ffi_type_uint, I_set_sw, I_get_sw}, +#elif SIZEOF__BOOL == SIZEOF_LONG + { 't', t_set, t_get, &ffi_type_ulong, L_set_sw, L_get_sw}, +#elif SIZEOF__BOOL == SIZEOF_LONG_LONG + { 't', t_set, t_get, &ffi_type_ulong, Q_set_sw, Q_get_sw}, +#endif /* SIZEOF__BOOL */ { 'O', O_set, O_get, &ffi_type_pointer}, { 0, NULL, NULL, NULL}, }; Modified: python/branches/p3yk/Modules/_ctypes/libffi/configure ============================================================================== --- python/branches/p3yk/Modules/_ctypes/libffi/configure (original) +++ python/branches/p3yk/Modules/_ctypes/libffi/configure Fri Apr 27 21:54:29 2007 @@ -934,7 +934,7 @@ else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi - cd "$ac_popdir" + cd $ac_popdir done fi @@ -1973,7 +1973,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2031,7 +2032,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2147,7 +2149,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2201,7 +2204,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2246,7 +2250,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2290,7 +2295,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2617,7 +2623,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2787,7 +2794,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2854,7 +2862,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3038,7 +3047,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3101,7 +3111,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3279,7 +3290,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3396,7 +3408,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3569,7 +3582,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3770,7 +3784,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3833,7 +3848,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3914,7 +3930,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4055,7 +4072,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4191,7 +4209,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4253,7 +4272,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4293,7 +4313,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4349,7 +4370,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4389,7 +4411,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4453,7 +4476,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4484,8 +4508,10 @@ esac else if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 -echo "$as_me: error: internal error: not reached in cross-compile" >&2;} + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF @@ -4597,7 +4623,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4659,7 +4686,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4699,7 +4727,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4755,7 +4784,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4795,7 +4825,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4859,7 +4890,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4890,8 +4922,10 @@ esac else if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 -echo "$as_me: error: internal error: not reached in cross-compile" >&2;} + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF @@ -4986,6 +5020,479 @@ fi +echo "$as_me:$LINENO: checking for _Bool support" >&5 +echo $ECHO_N "checking for _Bool support... $ECHO_C" >&6 +have_c99_bool=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +_Bool x; x = (_Bool)0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_C99_BOOL 1 +_ACEOF + + have_c99_bool=yes + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $have_c99_bool" >&5 +echo "${ECHO_T}$have_c99_bool" >&6 +if test "$have_c99_bool" = yes ; then +echo "$as_me:$LINENO: checking for _Bool" >&5 +echo $ECHO_N "checking for _Bool... $ECHO_C" >&6 +if test "${ac_cv_type__Bool+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((_Bool *) 0) + return 0; +if (sizeof (_Bool)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type__Bool=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type__Bool=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type__Bool" >&5 +echo "${ECHO_T}$ac_cv_type__Bool" >&6 + +echo "$as_me:$LINENO: checking size of _Bool" >&5 +echo $ECHO_N "checking size of _Bool... $ECHO_C" >&6 +if test "${ac_cv_sizeof__Bool+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type__Bool" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (_Bool))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (_Bool))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (_Bool))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (_Bool))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (_Bool))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof__Bool=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (_Bool), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (_Bool), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (_Bool)); } +unsigned long ulongval () { return (long) (sizeof (_Bool)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (_Bool))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (_Bool)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (_Bool)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof__Bool=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (_Bool), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (_Bool), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof__Bool=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof__Bool" >&5 +echo "${ECHO_T}$ac_cv_sizeof__Bool" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF__BOOL $ac_cv_sizeof__Bool +_ACEOF + + +fi + echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 if test "${ac_cv_c_bigendian+set}" = set; then @@ -5021,7 +5528,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5063,7 +5571,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5120,7 +5629,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5252,7 +5762,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5318,7 +5829,8 @@ cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -6277,6 +6789,11 @@ + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ @@ -6315,12 +6832,6 @@ fi;; esac done` || { (exit 1); exit 1; } - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub Modified: python/branches/p3yk/Modules/_ctypes/libffi/configure.ac ============================================================================== --- python/branches/p3yk/Modules/_ctypes/libffi/configure.ac (original) +++ python/branches/p3yk/Modules/_ctypes/libffi/configure.ac Fri Apr 27 21:54:29 2007 @@ -106,6 +106,17 @@ fi AC_SUBST(HAVE_LONG_DOUBLE) +AC_MSG_CHECKING(for _Bool support) +have_c99_bool=no +AC_TRY_COMPILE([], [_Bool x; x = (_Bool)0;], [ + AC_DEFINE(HAVE_C99_BOOL, 1, [Define this if you have the type _Bool.]) + have_c99_bool=yes +]) +AC_MSG_RESULT($have_c99_bool) +if test "$have_c99_bool" = yes ; then +AC_CHECK_SIZEOF(_Bool, 1) +fi + AC_C_BIGENDIAN AH_VERBATIM([WORDS_BIGENDIAN], [ Modified: python/branches/p3yk/Modules/_ctypes/libffi/fficonfig.h.in ============================================================================== --- python/branches/p3yk/Modules/_ctypes/libffi/fficonfig.h.in (original) +++ python/branches/p3yk/Modules/_ctypes/libffi/fficonfig.h.in Fri Apr 27 21:54:29 2007 @@ -28,6 +28,9 @@ */ #undef HAVE_AS_SPARC_UA_PCREL +/* Define this if you have the type _Bool. */ +#undef HAVE_C99_BOOL + /* Define if __attribute__((visibility("hidden"))) is supported. */ #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE @@ -103,6 +106,9 @@ /* The size of a `long double', as computed by sizeof. */ #undef SIZEOF_LONG_DOUBLE +/* The size of a `_Bool', as computed by sizeof. */ +#undef SIZEOF__BOOL + /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. Modified: python/branches/p3yk/Modules/_cursesmodule.c ============================================================================== --- python/branches/p3yk/Modules/_cursesmodule.c (original) +++ python/branches/p3yk/Modules/_cursesmodule.c Fri Apr 27 21:54:29 2007 @@ -35,19 +35,22 @@ /* -A number of SysV or ncurses functions don't have wrappers yet; if you need -a given function, add it and send a patch. Here's a list of currently -unsupported functions: +A number of SysV or ncurses functions don't have wrappers yet; if you +need a given function, add it and send a patch. See +http://www.python.org/dev/patches/ for instructions on how to submit +patches to Python. - addchnstr addchstr chgat color_set define_key +Here's a list of currently unsupported functions: + + addchnstr addchstr color_set define_key del_curterm delscreen dupwin inchnstr inchstr innstr keyok - mcprint mvaddchnstr mvaddchstr mvchgat mvcur mvinchnstr - mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr mvwchgat + mcprint mvaddchnstr mvaddchstr mvcur mvinchnstr + mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr mvwinchnstr mvwinchstr mvwinnstr newterm restartterm ripoffline scr_dump scr_init scr_restore scr_set scrl set_curterm set_term setterm tgetent tgetflag tgetnum tgetstr tgoto timeout tputs - vidattr vidputs waddchnstr waddchstr wchgat + vidattr vidputs waddchnstr waddchstr wcolor_set winchnstr winchstr winnstr wmouse_trafo wscrl Low-priority: @@ -620,6 +623,56 @@ } #endif +/* chgat, added by Fabian Kreutz */ + +static PyObject * +PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) +{ + int rtn; + int x, y; + int num = -1; + short color; + attr_t attr = A_NORMAL; + int use_xy = FALSE; + + switch (PyTuple_Size(args)) { + case 1: + if (!PyArg_ParseTuple(args,"l;attr", &attr)) + return NULL; + break; + case 2: + if (!PyArg_ParseTuple(args,"il;n,attr", &num, &attr)) + return NULL; + break; + case 3: + if (!PyArg_ParseTuple(args,"iil;int,int,attr", &y, &x, &attr)) + return NULL; + use_xy = TRUE; + break; + case 4: + if (!PyArg_ParseTuple(args,"iiil;int,int,n,attr", &y, &x, &num, &attr)) + return NULL; + use_xy = TRUE; + break; + default: + PyErr_SetString(PyExc_TypeError, "chgat requires 1 to 4 arguments"); + return NULL; + } + + color = (short)((attr >> 8) & 0xff); + attr = attr - (color << 8); + + if (use_xy == TRUE) { + rtn = mvwchgat(self->win,y,x,num,attr,color,NULL); + touchline(self->win,y,1); + } else { + getyx(self->win,y,x); + rtn = wchgat(self->win,num,attr,color,NULL); + touchline(self->win,y,1); + } + return PyCursesCheckERR(rtn, "chgat"); +} + static PyObject * PyCursesWindow_DelCh(PyCursesWindowObject *self, PyObject *args) @@ -1428,6 +1481,7 @@ {"attron", (PyCFunction)PyCursesWindow_wattron, METH_VARARGS}, {"attrset", (PyCFunction)PyCursesWindow_wattrset, METH_VARARGS}, {"bkgd", (PyCFunction)PyCursesWindow_Bkgd, METH_VARARGS}, + {"chgat", (PyCFunction)PyCursesWindow_ChgAt, METH_VARARGS}, {"bkgdset", (PyCFunction)PyCursesWindow_BkgdSet, METH_VARARGS}, {"border", (PyCFunction)PyCursesWindow_Border, METH_VARARGS}, {"box", (PyCFunction)PyCursesWindow_Box, METH_VARARGS}, @@ -2196,19 +2250,72 @@ } } +/* Internal helper used for updating curses.LINES, curses.COLS, _curses.LINES + * and _curses.COLS */ +static int +update_lines_cols(void) +{ + PyObject *o; + PyObject *m = PyImport_ImportModule("curses"); + + if (!m) + return 0; + + o = PyInt_FromLong(LINES); + if (!o) { + Py_DECREF(m); + return 0; + } + if (PyObject_SetAttrString(m, "LINES", o)) { + Py_DECREF(m); + Py_DECREF(o); + return 0; + } + if (PyDict_SetItemString(ModDict, "LINES", o)) { + Py_DECREF(m); + Py_DECREF(o); + return 0; + } + Py_DECREF(o); + o = PyInt_FromLong(COLS); + if (!o) { + Py_DECREF(m); + return 0; + } + if (PyObject_SetAttrString(m, "COLS", o)) { + Py_DECREF(m); + Py_DECREF(o); + return 0; + } + if (PyDict_SetItemString(ModDict, "COLS", o)) { + Py_DECREF(m); + Py_DECREF(o); + return 0; + } + Py_DECREF(o); + Py_DECREF(m); + return 1; +} + #ifdef HAVE_CURSES_RESIZETERM static PyObject * PyCurses_ResizeTerm(PyObject *self, PyObject *args) { int lines; int columns; + PyObject *result; PyCursesInitialised if (!PyArg_ParseTuple(args,"ii:resizeterm", &lines, &columns)) return NULL; - return PyCursesCheckERR(resizeterm(lines, columns), "resizeterm"); + result = PyCursesCheckERR(resizeterm(lines, columns), "resizeterm"); + if (!result) + return NULL; + if (!update_lines_cols()) + return NULL; + return result; } #endif @@ -2220,12 +2327,19 @@ int lines; int columns; + PyObject *result; + PyCursesInitialised if (!PyArg_ParseTuple(args,"ii:resize_term", &lines, &columns)) return NULL; - return PyCursesCheckERR(resize_term(lines, columns), "resize_term"); + result = PyCursesCheckERR(resize_term(lines, columns), "resize_term"); + if (!result) + return NULL; + if (!update_lines_cols()) + return NULL; + return result; } #endif /* HAVE_CURSES_RESIZE_TERM */ Modified: python/branches/p3yk/Modules/_localemodule.c ============================================================================== --- python/branches/p3yk/Modules/_localemodule.c (original) +++ python/branches/p3yk/Modules/_localemodule.c Fri Apr 27 21:54:29 2007 @@ -360,7 +360,7 @@ buf = PyMem_Malloc(n1); if (!buf) return PyErr_NoMemory(); - n2 = strxfrm(buf, s, n1); + n2 = strxfrm(buf, s, n1) + 1; if (n2 > n1) { /* more space needed */ buf = PyMem_Realloc(buf, n2); Modified: python/branches/p3yk/Modules/_struct.c ============================================================================== --- python/branches/p3yk/Modules/_struct.c (original) +++ python/branches/p3yk/Modules/_struct.c Fri Apr 27 21:54:29 2007 @@ -847,7 +847,7 @@ } while (--i > 0); /* Extend the sign bit. */ if (SIZEOF_LONG_LONG > f->size) - x |= -(x & (1L << ((8 * f->size) - 1))); + x |= -(x & ((PY_LONG_LONG)1 << ((8 * f->size) - 1))); if (x >= LONG_MIN && x <= LONG_MAX) return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); return PyLong_FromLongLong(x); @@ -1083,7 +1083,7 @@ } while (i > 0); /* Extend the sign bit. */ if (SIZEOF_LONG_LONG > f->size) - x |= -(x & (1L << ((8 * f->size) - 1))); + x |= -(x & ((PY_LONG_LONG)1 << ((8 * f->size) - 1))); if (x >= LONG_MIN && x <= LONG_MAX) return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); return PyLong_FromLongLong(x); @@ -1532,21 +1532,35 @@ static PyObject * s_unpack(PyObject *self, PyObject *inputstr) { + char *start; + Py_ssize_t len; + PyObject *args=NULL, *result; PyStructObject *soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->s_codes != NULL); - if (inputstr != NULL && PyBytes_Check(inputstr) && - PyBytes_GET_SIZE(inputstr) == soself->s_size) { - return s_unpack_internal(soself, PyBytes_AS_STRING(inputstr)); + if (inputstr == NULL) + goto fail; + if (PyString_Check(inputstr) && + PyString_GET_SIZE(inputstr) == soself->s_size) { + return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); } - if (inputstr == NULL || !PyString_Check(inputstr) || - PyString_GET_SIZE(inputstr) != soself->s_size) { - PyErr_Format(StructError, - "unpack requires a string argument of length %zd", - soself->s_size); + args = PyTuple_Pack(1, inputstr); + if (args == NULL) return NULL; - } - return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); + if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len)) + goto fail; + if (soself->s_size != len) + goto fail; + result = s_unpack_internal(soself, start); + Py_DECREF(args); + return result; + +fail: + Py_XDECREF(args); + PyErr_Format(StructError, + "unpack requires a string argument of length %zd", + soself->s_size); + return NULL; } PyDoc_STRVAR(s_unpack_from__doc__, Modified: python/branches/p3yk/Modules/arraymodule.c ============================================================================== --- python/branches/p3yk/Modules/arraymodule.c (original) +++ python/branches/p3yk/Modules/arraymodule.c Fri Apr 27 21:54:29 2007 @@ -1147,12 +1147,19 @@ dict = Py_None; Py_INCREF(dict); } - result = Py_BuildValue("O(cs#)O", - array->ob_type, - array->ob_descr->typecode, - array->ob_item, - array->ob_size * array->ob_descr->itemsize, - dict); + if (array->ob_size > 0) { + result = Py_BuildValue("O(cs#)O", + array->ob_type, + array->ob_descr->typecode, + array->ob_item, + array->ob_size * array->ob_descr->itemsize, + dict); + } else { + result = Py_BuildValue("O(c)O", + array->ob_type, + array->ob_descr->typecode, + dict); + } Py_DECREF(dict); return result; } @@ -1762,6 +1769,8 @@ (objobjargproc)array_ass_subscr }; +static const void *emptybuf = ""; + static Py_ssize_t array_buffer_getreadbuf(arrayobject *self, Py_ssize_t index, const void **ptr) { @@ -1771,6 +1780,8 @@ return -1; } *ptr = (void *)self->ob_item; + if (*ptr == NULL) + *ptr = emptybuf; return self->ob_size*self->ob_descr->itemsize; } @@ -1783,6 +1794,8 @@ return -1; } *ptr = (void *)self->ob_item; + if (*ptr == NULL) + *ptr = emptybuf; return self->ob_size*self->ob_descr->itemsize; } Modified: python/branches/p3yk/Modules/binascii.c ============================================================================== --- python/branches/p3yk/Modules/binascii.c (original) +++ python/branches/p3yk/Modules/binascii.c Fri Apr 27 21:54:29 2007 @@ -1160,12 +1160,14 @@ if ((data[in] > 126) || (data[in] == '=') || (header && data[in] == '_') || - ((data[in] == '.') && (linelen == 1)) || + ((data[in] == '.') && (linelen == 0) && + (data[in+1] == '\n' || data[in+1] == '\r' || data[in+1] == 0)) || (!istext && ((data[in] == '\r') || (data[in] == '\n'))) || ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || ((data[in] < 33) && (data[in] != '\r') && (data[in] != '\n') && - (quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) + (quotetabs || + (!quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) { if ((linelen + 3) >= MAXLINESIZE) { linelen = 0; @@ -1230,12 +1232,14 @@ if ((data[in] > 126) || (data[in] == '=') || (header && data[in] == '_') || - ((data[in] == '.') && (linelen == 1)) || + ((data[in] == '.') && (linelen == 0) && + (data[in+1] == '\n' || data[in+1] == '\r' || data[in+1] == 0)) || (!istext && ((data[in] == '\r') || (data[in] == '\n'))) || ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || ((data[in] < 33) && (data[in] != '\r') && (data[in] != '\n') && - (quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) + (quotetabs || + (!quotetabs && ((data[in] != '\t') && (data[in] != ' ')))))) { if ((linelen + 3 )>= MAXLINESIZE) { odata[out++] = '='; Modified: python/branches/p3yk/Modules/bz2module.c ============================================================================== --- python/branches/p3yk/Modules/bz2module.c (original) +++ python/branches/p3yk/Modules/bz2module.c Fri Apr 27 21:54:29 2007 @@ -1553,6 +1553,8 @@ Util_CatchBZ2Error(bzerror); goto error; } + if (bzs->avail_in == 0) + break; /* no more input data */ if (bzs->avail_out == 0) { bufsize = Util_NewBufferSize(bufsize); if (_PyString_Resize(&ret, bufsize) < 0) { @@ -1562,8 +1564,6 @@ bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs) - totalout); bzs->avail_out = bufsize - (bzs->next_out - BUF(ret)); - } else if (bzs->avail_in == 0) { - break; } } @@ -1845,6 +1845,8 @@ Util_CatchBZ2Error(bzerror); goto error; } + if (bzs->avail_in == 0) + break; /* no more input data */ if (bzs->avail_out == 0) { bufsize = Util_NewBufferSize(bufsize); if (_PyString_Resize(&ret, bufsize) < 0) { @@ -1855,8 +1857,6 @@ bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs) - totalout); bzs->avail_out = bufsize - (bzs->next_out - BUF(ret)); - } else if (bzs->avail_in == 0) { - break; } } @@ -2134,6 +2134,13 @@ Py_DECREF(ret); return NULL; } + if (bzs->avail_in == 0) { + BZ2_bzDecompressEnd(bzs); + PyErr_SetString(PyExc_ValueError, + "couldn't find end of stream"); + Py_DECREF(ret); + return NULL; + } if (bzs->avail_out == 0) { bufsize = Util_NewBufferSize(bufsize); if (_PyString_Resize(&ret, bufsize) < 0) { @@ -2143,12 +2150,6 @@ } bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs); bzs->avail_out = bufsize - (bzs->next_out - BUF(ret)); - } else if (bzs->avail_in == 0) { - BZ2_bzDecompressEnd(bzs); - PyErr_SetString(PyExc_ValueError, - "couldn't find end of stream"); - Py_DECREF(ret); - return NULL; } } Modified: python/branches/p3yk/Modules/cPickle.c ============================================================================== --- python/branches/p3yk/Modules/cPickle.c (original) +++ python/branches/p3yk/Modules/cPickle.c Fri Apr 27 21:54:29 2007 @@ -533,11 +533,12 @@ self->buf_size = size; } else if (n > self->buf_size) { - self->buf = (char *)realloc(self->buf, n); - if (!self->buf) { + char *newbuf = (char *)realloc(self->buf, n); + if (!newbuf) { PyErr_NoMemory(); return -1; } + self->buf = newbuf; self->buf_size = n; } @@ -576,6 +577,7 @@ i = 0; while (1) { int bigger; + char *newbuf; for (; i < (self->buf_size - 1); i++) { if (feof(self->fp) || (self->buf[i] = getc(self->fp)) == '\n') { @@ -589,11 +591,12 @@ PyErr_NoMemory(); return -1; } - self->buf = (char *)realloc(self->buf, bigger); - if (!self->buf) { + newbuf = (char *)realloc(self->buf, bigger); + if (!newbuf) { PyErr_NoMemory(); return -1; } + self->buf = newbuf; self->buf_size = bigger; } } @@ -4199,17 +4202,19 @@ */ if ((self->num_marks + 1) >= self->marks_size) { + int *marks; s=self->marks_size+20; if (s <= self->num_marks) s=self->num_marks + 1; if (self->marks == NULL) - self->marks=(int *)malloc(s * sizeof(int)); + marks=(int *)malloc(s * sizeof(int)); else - self->marks=(int *)realloc(self->marks, + marks=(int *)realloc(self->marks, s * sizeof(int)); - if (! self->marks) { + if (!marks) { PyErr_NoMemory(); return -1; } + self->marks = marks; self->marks_size = s; } Modified: python/branches/p3yk/Modules/cStringIO.c ============================================================================== --- python/branches/p3yk/Modules/cStringIO.c (original) +++ python/branches/p3yk/Modules/cStringIO.c Fri Apr 27 21:54:29 2007 @@ -348,13 +348,17 @@ } if (position > self->buf_size) { + char *newbuf; self->buf_size*=2; if (self->buf_size <= position) self->buf_size=position+1; - self->buf = (char*) realloc(self->buf,self->buf_size); - if (!self->buf) { + newbuf = (char*) realloc(self->buf,self->buf_size); + if (!newbuf) { + free(self->buf); + self->buf = 0; self->buf_size=self->pos=0; return PyErr_NoMemory(); } + self->buf = newbuf; } else if (position < 0) position=0; @@ -375,6 +379,7 @@ O_cwrite(PyObject *self, const char *c, Py_ssize_t l) { Py_ssize_t newl; Oobject *oself; + char *newbuf; if (!IO__opencheck(IOOOBJECT(self))) return -1; oself = (Oobject *)self; @@ -386,12 +391,15 @@ assert(newl + 1 < INT_MAX); oself->buf_size = (int)(newl+1); } - oself->buf = (char*)realloc(oself->buf, oself->buf_size); - if (!oself->buf) { + newbuf = (char*)realloc(oself->buf, oself->buf_size); + if (!newbuf) { PyErr_SetString(PyExc_MemoryError,"out of memory"); + free(oself->buf); + oself->buf = 0; oself->buf_size = oself->pos = 0; return -1; } + oself->buf = newbuf; } memcpy(oself->buf+oself->pos,c,l); Deleted: /python/branches/p3yk/Modules/collectionsmodule.c ============================================================================== --- /python/branches/p3yk/Modules/collectionsmodule.c Fri Apr 27 21:54:29 2007 +++ (empty file) @@ -1,1373 +0,0 @@ -#include "Python.h" -#include "structmember.h" - -/* collections module implementation of a deque() datatype - Written and maintained by Raymond D. Hettinger - Copyright (c) 2004 Python Software Foundation. - All rights reserved. -*/ - -/* The block length may be set to any number over 1. Larger numbers - * reduce the number of calls to the memory allocator but take more - * memory. Ideally, BLOCKLEN should be set with an eye to the - * length of a cache line. - */ - -#define BLOCKLEN 62 -#define CENTER ((BLOCKLEN - 1) / 2) - -/* A `dequeobject` is composed of a doubly-linked list of `block` nodes. - * This list is not circular (the leftmost block has leftlink==NULL, - * and the rightmost block has rightlink==NULL). A deque d's first - * element is at d.leftblock[leftindex] and its last element is at - * d.rightblock[rightindex]; note that, unlike as for Python slice - * indices, these indices are inclusive on both ends. By being inclusive - * on both ends, algorithms for left and right operations become - * symmetrical which simplifies the design. - * - * The list of blocks is never empty, so d.leftblock and d.rightblock - * are never equal to NULL. - * - * The indices, d.leftindex and d.rightindex are always in the range - * 0 <= index < BLOCKLEN. - * Their exact relationship is: - * (d.leftindex + d.len - 1) % BLOCKLEN == d.rightindex. - * - * Empty deques have d.len == 0; d.leftblock==d.rightblock; - * d.leftindex == CENTER+1; and d.rightindex == CENTER. - * Checking for d.len == 0 is the intended way to see whether d is empty. - * - * Whenever d.leftblock == d.rightblock, - * d.leftindex + d.len - 1 == d.rightindex. - * - * However, when d.leftblock != d.rightblock, d.leftindex and d.rightindex - * become indices into distinct blocks and either may be larger than the - * other. - */ - -typedef struct BLOCK { - struct BLOCK *leftlink; - struct BLOCK *rightlink; - PyObject *data[BLOCKLEN]; -} block; - -static block * -newblock(block *leftlink, block *rightlink, int len) { - block *b; - /* To prevent len from overflowing INT_MAX on 64-bit machines, we - * refuse to allocate new blocks if the current len is dangerously - * close. There is some extra margin to prevent spurious arithmetic - * overflows at various places. The following check ensures that - * the blocks allocated to the deque, in the worst case, can only - * have INT_MAX-2 entries in total. - */ - if (len >= INT_MAX - 2*BLOCKLEN) { - PyErr_SetString(PyExc_OverflowError, - "cannot add more blocks to the deque"); - return NULL; - } - b = PyMem_Malloc(sizeof(block)); - if (b == NULL) { - PyErr_NoMemory(); - return NULL; - } - b->leftlink = leftlink; - b->rightlink = rightlink; - return b; -} - -typedef struct { - PyObject_HEAD - block *leftblock; - block *rightblock; - int leftindex; /* in range(BLOCKLEN) */ - int rightindex; /* in range(BLOCKLEN) */ - int len; - long state; /* incremented whenever the indices move */ - PyObject *weakreflist; /* List of weak references */ -} dequeobject; - -static PyTypeObject deque_type; - -static PyObject * -deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - dequeobject *deque; - block *b; - - if (type == &deque_type && !_PyArg_NoKeywords("deque()", kwds)) - return NULL; - - /* create dequeobject structure */ - deque = (dequeobject *)type->tp_alloc(type, 0); - if (deque == NULL) - return NULL; - - b = newblock(NULL, NULL, 0); - if (b == NULL) { - Py_DECREF(deque); - return NULL; - } - - assert(BLOCKLEN >= 2); - deque->leftblock = b; - deque->rightblock = b; - deque->leftindex = CENTER + 1; - deque->rightindex = CENTER; - deque->len = 0; - deque->state = 0; - deque->weakreflist = NULL; - - return (PyObject *)deque; -} - -static PyObject * -deque_append(dequeobject *deque, PyObject *item) -{ - deque->state++; - if (deque->rightindex == BLOCKLEN-1) { - block *b = newblock(deque->rightblock, NULL, deque->len); - if (b == NULL) - return NULL; - assert(deque->rightblock->rightlink == NULL); - deque->rightblock->rightlink = b; - deque->rightblock = b; - deque->rightindex = -1; - } - Py_INCREF(item); - deque->len++; - deque->rightindex++; - deque->rightblock->data[deque->rightindex] = item; - Py_RETURN_NONE; -} - -PyDoc_STRVAR(append_doc, "Add an element to the right side of the deque."); - -static PyObject * -deque_appendleft(dequeobject *deque, PyObject *item) -{ - deque->state++; - if (deque->leftindex == 0) { - block *b = newblock(NULL, deque->leftblock, deque->len); - if (b == NULL) - return NULL; - assert(deque->leftblock->leftlink == NULL); - deque->leftblock->leftlink = b; - deque->leftblock = b; - deque->leftindex = BLOCKLEN; - } - Py_INCREF(item); - deque->len++; - deque->leftindex--; - deque->leftblock->data[deque->leftindex] = item; - Py_RETURN_NONE; -} - -PyDoc_STRVAR(appendleft_doc, "Add an element to the left side of the deque."); - -static PyObject * -deque_pop(dequeobject *deque, PyObject *unused) -{ - PyObject *item; - block *prevblock; - - if (deque->len == 0) { - PyErr_SetString(PyExc_IndexError, "pop from an empty deque"); - return NULL; - } - item = deque->rightblock->data[deque->rightindex]; - deque->rightindex--; - deque->len--; - deque->state++; - - if (deque->rightindex == -1) { - if (deque->len == 0) { - assert(deque->leftblock == deque->rightblock); - assert(deque->leftindex == deque->rightindex+1); - /* re-center instead of freeing a block */ - deque->leftindex = CENTER + 1; - deque->rightindex = CENTER; - } else { - prevblock = deque->rightblock->leftlink; - assert(deque->leftblock != deque->rightblock); - PyMem_Free(deque->rightblock); - prevblock->rightlink = NULL; - deque->rightblock = prevblock; - deque->rightindex = BLOCKLEN - 1; - } - } - return item; -} - -PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element."); - -static PyObject * -deque_popleft(dequeobject *deque, PyObject *unused) -{ - PyObject *item; - block *prevblock; - - if (deque->len == 0) { - PyErr_SetString(PyExc_IndexError, "pop from an empty deque"); - return NULL; - } - assert(deque->leftblock != NULL); - item = deque->leftblock->data[deque->leftindex]; - deque->leftindex++; - deque->len--; - deque->state++; - - if (deque->leftindex == BLOCKLEN) { - if (deque->len == 0) { - assert(deque->leftblock == deque->rightblock); - assert(deque->leftindex == deque->rightindex+1); - /* re-center instead of freeing a block */ - deque->leftindex = CENTER + 1; - deque->rightindex = CENTER; - } else { - assert(deque->leftblock != deque->rightblock); - prevblock = deque->leftblock->rightlink; - PyMem_Free(deque->leftblock); - assert(prevblock != NULL); - prevblock->leftlink = NULL; - deque->leftblock = prevblock; - deque->leftindex = 0; - } - } - return item; -} - -PyDoc_STRVAR(popleft_doc, "Remove and return the leftmost element."); - -static PyObject * -deque_extend(dequeobject *deque, PyObject *iterable) -{ - PyObject *it, *item; - - it = PyObject_GetIter(iterable); - if (it == NULL) - return NULL; - - while ((item = PyIter_Next(it)) != NULL) { - deque->state++; - if (deque->rightindex == BLOCKLEN-1) { - block *b = newblock(deque->rightblock, NULL, - deque->len); - if (b == NULL) { - Py_DECREF(item); - Py_DECREF(it); - return NULL; - } - assert(deque->rightblock->rightlink == NULL); - deque->rightblock->rightlink = b; - deque->rightblock = b; - deque->rightindex = -1; - } - deque->len++; - deque->rightindex++; - deque->rightblock->data[deque->rightindex] = item; - } - Py_DECREF(it); - if (PyErr_Occurred()) - return NULL; - Py_RETURN_NONE; -} - -PyDoc_STRVAR(extend_doc, -"Extend the right side of the deque with elements from the iterable"); - -static PyObject * -deque_extendleft(dequeobject *deque, PyObject *iterable) -{ - PyObject *it, *item; - - it = PyObject_GetIter(iterable); - if (it == NULL) - return NULL; - - while ((item = PyIter_Next(it)) != NULL) { - deque->state++; - if (deque->leftindex == 0) { - block *b = newblock(NULL, deque->leftblock, - deque->len); - if (b == NULL) { - Py_DECREF(item); - Py_DECREF(it); - return NULL; - } - assert(deque->leftblock->leftlink == NULL); - deque->leftblock->leftlink = b; - deque->leftblock = b; - deque->leftindex = BLOCKLEN; - } - deque->len++; - deque->leftindex--; - deque->leftblock->data[deque->leftindex] = item; - } - Py_DECREF(it); - if (PyErr_Occurred()) - return NULL; - Py_RETURN_NONE; -} - -PyDoc_STRVAR(extendleft_doc, -"Extend the left side of the deque with elements from the iterable"); - -static int -_deque_rotate(dequeobject *deque, Py_ssize_t n) -{ - int i, len=deque->len, halflen=(len+1)>>1; - PyObject *item, *rv; - - if (len == 0) - return 0; - if (n > halflen || n < -halflen) { - n %= len; - if (n > halflen) - n -= len; - else if (n < -halflen) - n += len; - } - - for (i=0 ; in ; i--) { - item = deque_popleft(deque, NULL); - assert (item != NULL); - rv = deque_append(deque, item); - Py_DECREF(item); - if (rv == NULL) - return -1; - Py_DECREF(rv); - } - return 0; -} - -static PyObject * -deque_rotate(dequeobject *deque, PyObject *args) -{ - int n=1; - - if (!PyArg_ParseTuple(args, "|i:rotate", &n)) - return NULL; - if (_deque_rotate(deque, n) == 0) - Py_RETURN_NONE; - return NULL; -} - -PyDoc_STRVAR(rotate_doc, -"Rotate the deque n steps to the right (default n=1). If n is negative, rotates left."); - -static Py_ssize_t -deque_len(dequeobject *deque) -{ - return deque->len; -} - -static PyObject * -deque_remove(dequeobject *deque, PyObject *value) -{ - Py_ssize_t i, n=deque->len; - - for (i=0 ; ileftblock->data[deque->leftindex]; - int cmp = PyObject_RichCompareBool(item, value, Py_EQ); - - if (deque->len != n) { - PyErr_SetString(PyExc_IndexError, - "deque mutated during remove()."); - return NULL; - } - if (cmp > 0) { - PyObject *tgt = deque_popleft(deque, NULL); - assert (tgt != NULL); - Py_DECREF(tgt); - if (_deque_rotate(deque, i) == -1) - return NULL; - Py_RETURN_NONE; - } - else if (cmp < 0) { - _deque_rotate(deque, i); - return NULL; - } - _deque_rotate(deque, -1); - } - PyErr_SetString(PyExc_ValueError, "deque.remove(x): x not in deque"); - return NULL; -} - -PyDoc_STRVAR(remove_doc, -"D.remove(value) -- remove first occurrence of value."); - -static int -deque_clear(dequeobject *deque) -{ - PyObject *item; - - while (deque->len) { - item = deque_pop(deque, NULL); - assert (item != NULL); - Py_DECREF(item); - } - assert(deque->leftblock == deque->rightblock && - deque->leftindex - 1 == deque->rightindex && - deque->len == 0); - return 0; -} - -static PyObject * -deque_item(dequeobject *deque, int i) -{ - block *b; - PyObject *item; - int n, index=i; - - if (i < 0 || i >= deque->len) { - PyErr_SetString(PyExc_IndexError, - "deque index out of range"); - return NULL; - } - - if (i == 0) { - i = deque->leftindex; - b = deque->leftblock; - } else if (i == deque->len - 1) { - i = deque->rightindex; - b = deque->rightblock; - } else { - i += deque->leftindex; - n = i / BLOCKLEN; - i %= BLOCKLEN; - if (index < (deque->len >> 1)) { - b = deque->leftblock; - while (n--) - b = b->rightlink; - } else { - n = (deque->leftindex + deque->len - 1) / BLOCKLEN - n; - b = deque->rightblock; - while (n--) - b = b->leftlink; - } - } - item = b->data[i]; - Py_INCREF(item); - return item; -} - -/* delitem() implemented in terms of rotate for simplicity and reasonable - performance near the end points. If for some reason this method becomes - popular, it is not hard to re-implement this using direct data movement - (similar to code in list slice assignment) and achieve a two or threefold - performance boost. -*/ - -static int -deque_del_item(dequeobject *deque, Py_ssize_t i) -{ - PyObject *item; - - assert (i >= 0 && i < deque->len); - if (_deque_rotate(deque, -i) == -1) - return -1; - - item = deque_popleft(deque, NULL); - assert (item != NULL); - Py_DECREF(item); - - return _deque_rotate(deque, i); -} - -static int -deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v) -{ - PyObject *old_value; - block *b; - Py_ssize_t n, len=deque->len, halflen=(len+1)>>1, index=i; - - if (i < 0 || i >= len) { - PyErr_SetString(PyExc_IndexError, - "deque index out of range"); - return -1; - } - if (v == NULL) - return deque_del_item(deque, i); - - i += deque->leftindex; - n = i / BLOCKLEN; - i %= BLOCKLEN; - if (index <= halflen) { - b = deque->leftblock; - while (n--) - b = b->rightlink; - } else { - n = (deque->leftindex + len - 1) / BLOCKLEN - n; - b = deque->rightblock; - while (n--) - b = b->leftlink; - } - Py_INCREF(v); - old_value = b->data[i]; - b->data[i] = v; - Py_DECREF(old_value); - return 0; -} - -static PyObject * -deque_clearmethod(dequeobject *deque) -{ - int rv; - - rv = deque_clear(deque); - assert (rv != -1); - Py_RETURN_NONE; -} - -PyDoc_STRVAR(clear_doc, "Remove all elements from the deque."); - -static void -deque_dealloc(dequeobject *deque) -{ - PyObject_GC_UnTrack(deque); - if (deque->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) deque); - if (deque->leftblock != NULL) { - deque_clear(deque); - assert(deque->leftblock != NULL); - PyMem_Free(deque->leftblock); - } - deque->leftblock = NULL; - deque->rightblock = NULL; - deque->ob_type->tp_free(deque); -} - -static int -deque_traverse(dequeobject *deque, visitproc visit, void *arg) -{ - block *b; - PyObject *item; - int index; - int indexlo = deque->leftindex; - - for (b = deque->leftblock; b != NULL; b = b->rightlink) { - const int indexhi = b == deque->rightblock ? - deque->rightindex : - BLOCKLEN - 1; - - for (index = indexlo; index <= indexhi; ++index) { - item = b->data[index]; - Py_VISIT(item); - } - indexlo = 0; - } - return 0; -} - -static long -deque_nohash(PyObject *self) -{ - PyErr_SetString(PyExc_TypeError, "deque objects are unhashable"); - return -1; -} - -static PyObject * -deque_copy(PyObject *deque) -{ - return PyObject_CallFunctionObjArgs((PyObject *)(deque->ob_type), - deque, NULL); -} - -PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque."); - -static PyObject * -deque_reduce(dequeobject *deque) -{ - PyObject *dict, *result, *it; - - dict = PyObject_GetAttrString((PyObject *)deque, "__dict__"); - if (dict == NULL) { - PyErr_Clear(); - dict = Py_None; - Py_INCREF(dict); - } - it = PyObject_GetIter((PyObject *)deque); - if (it == NULL) { - Py_DECREF(dict); - return NULL; - } - result = Py_BuildValue("O()ON", deque->ob_type, dict, it); - Py_DECREF(dict); - return result; -} - -PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); - -static PyObject * -deque_repr(PyObject *deque) -{ - PyObject *aslist, *result, *fmt; - int i; - - i = Py_ReprEnter(deque); - if (i != 0) { - if (i < 0) - return NULL; - return PyString_FromString("[...]"); - } - - aslist = PySequence_List(deque); - if (aslist == NULL) { - Py_ReprLeave(deque); - return NULL; - } - - fmt = PyString_FromString("deque(%r)"); - if (fmt == NULL) { - Py_DECREF(aslist); - Py_ReprLeave(deque); - return NULL; - } - result = PyString_Format(fmt, aslist); - Py_DECREF(fmt); - Py_DECREF(aslist); - Py_ReprLeave(deque); - return result; -} - -static int -deque_tp_print(PyObject *deque, FILE *fp, int flags) -{ - PyObject *it, *item; - char *emit = ""; /* No separator emitted on first pass */ - char *separator = ", "; - int i; - - i = Py_ReprEnter(deque); - if (i != 0) { - if (i < 0) - return i; - fputs("[...]", fp); - return 0; - } - - it = PyObject_GetIter(deque); - if (it == NULL) - return -1; - - fputs("deque([", fp); - while ((item = PyIter_Next(it)) != NULL) { - fputs(emit, fp); - emit = separator; - if (PyObject_Print(item, fp, 0) != 0) { - Py_DECREF(item); - Py_DECREF(it); - Py_ReprLeave(deque); - return -1; - } - Py_DECREF(item); - } - Py_ReprLeave(deque); - Py_DECREF(it); - if (PyErr_Occurred()) - return -1; - fputs("])", fp); - return 0; -} - -static PyObject * -deque_richcompare(PyObject *v, PyObject *w, int op) -{ - PyObject *it1=NULL, *it2=NULL, *x, *y; - int b, vs, ws, cmp=-1; - - if (!PyObject_TypeCheck(v, &deque_type) || - !PyObject_TypeCheck(w, &deque_type)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - - /* Shortcuts */ - vs = ((dequeobject *)v)->len; - ws = ((dequeobject *)w)->len; - if (op == Py_EQ) { - if (v == w) - Py_RETURN_TRUE; - if (vs != ws) - Py_RETURN_FALSE; - } - if (op == Py_NE) { - if (v == w) - Py_RETURN_FALSE; - if (vs != ws) - Py_RETURN_TRUE; - } - - /* Search for the first index where items are different */ - it1 = PyObject_GetIter(v); - if (it1 == NULL) - goto done; - it2 = PyObject_GetIter(w); - if (it2 == NULL) - goto done; - for (;;) { - x = PyIter_Next(it1); - if (x == NULL && PyErr_Occurred()) - goto done; - y = PyIter_Next(it2); - if (x == NULL || y == NULL) - break; - b = PyObject_RichCompareBool(x, y, Py_EQ); - if (b == 0) { - cmp = PyObject_RichCompareBool(x, y, op); - Py_DECREF(x); - Py_DECREF(y); - goto done; - } - Py_DECREF(x); - Py_DECREF(y); - if (b == -1) - goto done; - } - /* We reached the end of one deque or both */ - Py_XDECREF(x); - Py_XDECREF(y); - if (PyErr_Occurred()) - goto done; - switch (op) { - case Py_LT: cmp = y != NULL; break; /* if w was longer */ - case Py_LE: cmp = x == NULL; break; /* if v was not longer */ - case Py_EQ: cmp = x == y; break; /* if we reached the end of both */ - case Py_NE: cmp = x != y; break; /* if one deque continues */ - case Py_GT: cmp = x != NULL; break; /* if v was longer */ - case Py_GE: cmp = y == NULL; break; /* if w was not longer */ - } - -done: - Py_XDECREF(it1); - Py_XDECREF(it2); - if (cmp == 1) - Py_RETURN_TRUE; - if (cmp == 0) - Py_RETURN_FALSE; - return NULL; -} - -static int -deque_init(dequeobject *deque, PyObject *args, PyObject *kwds) -{ - PyObject *iterable = NULL; - - if (!PyArg_UnpackTuple(args, "deque", 0, 1, &iterable)) - return -1; - - if (iterable != NULL) { - PyObject *rv = deque_extend(deque, iterable); - if (rv == NULL) - return -1; - Py_DECREF(rv); - } - return 0; -} - -static PySequenceMethods deque_as_sequence = { - (lenfunc)deque_len, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - (ssizeargfunc)deque_item, /* sq_item */ - 0, /* sq_slice */ - (ssizeobjargproc)deque_ass_item, /* sq_ass_item */ -}; - -/* deque object ********************************************************/ - -static PyObject *deque_iter(dequeobject *deque); -static PyObject *deque_reviter(dequeobject *deque); -PyDoc_STRVAR(reversed_doc, - "D.__reversed__() -- return a reverse iterator over the deque"); - -static PyMethodDef deque_methods[] = { - {"append", (PyCFunction)deque_append, - METH_O, append_doc}, - {"appendleft", (PyCFunction)deque_appendleft, - METH_O, appendleft_doc}, - {"clear", (PyCFunction)deque_clearmethod, - METH_NOARGS, clear_doc}, - {"__copy__", (PyCFunction)deque_copy, - METH_NOARGS, copy_doc}, - {"extend", (PyCFunction)deque_extend, - METH_O, extend_doc}, - {"extendleft", (PyCFunction)deque_extendleft, - METH_O, extendleft_doc}, - {"pop", (PyCFunction)deque_pop, - METH_NOARGS, pop_doc}, - {"popleft", (PyCFunction)deque_popleft, - METH_NOARGS, popleft_doc}, - {"__reduce__", (PyCFunction)deque_reduce, - METH_NOARGS, reduce_doc}, - {"remove", (PyCFunction)deque_remove, - METH_O, remove_doc}, - {"__reversed__", (PyCFunction)deque_reviter, - METH_NOARGS, reversed_doc}, - {"rotate", (PyCFunction)deque_rotate, - METH_VARARGS, rotate_doc}, - {NULL, NULL} /* sentinel */ -}; - -PyDoc_STRVAR(deque_doc, -"deque(iterable) --> deque object\n\ -\n\ -Build an ordered collection accessible from endpoints only."); - -static PyTypeObject deque_type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "collections.deque", /* tp_name */ - sizeof(dequeobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)deque_dealloc, /* tp_dealloc */ - deque_tp_print, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - deque_repr, /* tp_repr */ - 0, /* tp_as_number */ - &deque_as_sequence, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - deque_nohash, /* 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 | - Py_TPFLAGS_HAVE_GC, /* tp_flags */ - deque_doc, /* tp_doc */ - (traverseproc)deque_traverse, /* tp_traverse */ - (inquiry)deque_clear, /* tp_clear */ - (richcmpfunc)deque_richcompare, /* tp_richcompare */ - offsetof(dequeobject, weakreflist), /* tp_weaklistoffset*/ - (getiterfunc)deque_iter, /* tp_iter */ - 0, /* tp_iternext */ - deque_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 */ - (initproc)deque_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - deque_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - -/*********************** Deque Iterator **************************/ - -typedef struct { - PyObject_HEAD - int index; - block *b; - dequeobject *deque; - long state; /* state when the iterator is created */ - int counter; /* number of items remaining for iteration */ -} dequeiterobject; - -PyTypeObject dequeiter_type; - -static PyObject * -deque_iter(dequeobject *deque) -{ - dequeiterobject *it; - - it = PyObject_New(dequeiterobject, &dequeiter_type); - if (it == NULL) - return NULL; - it->b = deque->leftblock; - it->index = deque->leftindex; - Py_INCREF(deque); - it->deque = deque; - it->state = deque->state; - it->counter = deque->len; - return (PyObject *)it; -} - -static void -dequeiter_dealloc(dequeiterobject *dio) -{ - Py_XDECREF(dio->deque); - dio->ob_type->tp_free(dio); -} - -static PyObject * -dequeiter_next(dequeiterobject *it) -{ - PyObject *item; - - if (it->deque->state != it->state) { - it->counter = 0; - PyErr_SetString(PyExc_RuntimeError, - "deque mutated during iteration"); - return NULL; - } - if (it->counter == 0) - return NULL; - assert (!(it->b == it->deque->rightblock && - it->index > it->deque->rightindex)); - - item = it->b->data[it->index]; - it->index++; - it->counter--; - if (it->index == BLOCKLEN && it->counter > 0) { - assert (it->b->rightlink != NULL); - it->b = it->b->rightlink; - it->index = 0; - } - Py_INCREF(item); - return item; -} - -static PyObject * -dequeiter_len(dequeiterobject *it) -{ - return PyInt_FromLong(it->counter); -} - -PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); - -static PyMethodDef dequeiter_methods[] = { - {"__length_hint__", (PyCFunction)dequeiter_len, METH_NOARGS, length_hint_doc}, - {NULL, NULL} /* sentinel */ -}; - -PyTypeObject dequeiter_type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "deque_iterator", /* tp_name */ - sizeof(dequeiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dequeiter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* 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, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dequeiter_next, /* tp_iternext */ - dequeiter_methods, /* tp_methods */ - 0, -}; - -/*********************** Deque Reverse Iterator **************************/ - -PyTypeObject dequereviter_type; - -static PyObject * -deque_reviter(dequeobject *deque) -{ - dequeiterobject *it; - - it = PyObject_New(dequeiterobject, &dequereviter_type); - if (it == NULL) - return NULL; - it->b = deque->rightblock; - it->index = deque->rightindex; - Py_INCREF(deque); - it->deque = deque; - it->state = deque->state; - it->counter = deque->len; - return (PyObject *)it; -} - -static PyObject * -dequereviter_next(dequeiterobject *it) -{ - PyObject *item; - if (it->counter == 0) - return NULL; - - if (it->deque->state != it->state) { - it->counter = 0; - PyErr_SetString(PyExc_RuntimeError, - "deque mutated during iteration"); - return NULL; - } - assert (!(it->b == it->deque->leftblock && - it->index < it->deque->leftindex)); - - item = it->b->data[it->index]; - it->index--; - it->counter--; - if (it->index == -1 && it->counter > 0) { - assert (it->b->leftlink != NULL); - it->b = it->b->leftlink; - it->index = BLOCKLEN - 1; - } - Py_INCREF(item); - return item; -} - -PyTypeObject dequereviter_type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "deque_reverse_iterator", /* tp_name */ - sizeof(dequeiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dequeiter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* 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, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dequereviter_next, /* tp_iternext */ - dequeiter_methods, /* tp_methods */ - 0, -}; - -/* defaultdict type *********************************************************/ - -typedef struct { - PyDictObject dict; - PyObject *default_factory; -} defdictobject; - -static PyTypeObject defdict_type; /* Forward */ - -PyDoc_STRVAR(defdict_missing_doc, -"__missing__(key) # Called by __getitem__ for missing key; pseudo-code:\n\ - if self.default_factory is None: raise KeyError(key)\n\ - self[key] = value = self.default_factory()\n\ - return value\n\ -"); - -static PyObject * -defdict_missing(defdictobject *dd, PyObject *key) -{ - PyObject *factory = dd->default_factory; - PyObject *value; - if (factory == NULL || factory == Py_None) { - /* XXX Call dict.__missing__(key) */ - PyErr_SetObject(PyExc_KeyError, key); - return NULL; - } - value = PyEval_CallObject(factory, NULL); - if (value == NULL) - return value; - if (PyObject_SetItem((PyObject *)dd, key, value) < 0) { - Py_DECREF(value); - return NULL; - } - return value; -} - -PyDoc_STRVAR(defdict_copy_doc, "D.copy() -> a shallow copy of D."); - -static PyObject * -defdict_copy(defdictobject *dd) -{ - /* This calls the object's class. That only works for subclasses - whose class constructor has the same signature. Subclasses that - define a different constructor signature must override copy(). - */ - return PyObject_CallFunctionObjArgs((PyObject *)dd->dict.ob_type, - dd->default_factory, dd, NULL); -} - -static PyObject * -defdict_reduce(defdictobject *dd) -{ - /* __reduce__ must return a 5-tuple as follows: - - - factory function - - tuple of args for the factory function - - additional state (here None) - - sequence iterator (here None) - - dictionary iterator (yielding successive (key, value) pairs - - This API is used by pickle.py and copy.py. - - For this to be useful with pickle.py, the default_factory - must be picklable; e.g., None, a built-in, or a global - function in a module or package. - - Both shallow and deep copying are supported, but for deep - copying, the default_factory must be deep-copyable; e.g. None, - or a built-in (functions are not copyable at this time). - - This only works for subclasses as long as their constructor - signature is compatible; the first argument must be the - optional default_factory, defaulting to None. - */ - PyObject *args; - PyObject *items; - PyObject *iteritems; - PyObject *result; - if (dd->default_factory == NULL || dd->default_factory == Py_None) - args = PyTuple_New(0); - else - args = PyTuple_Pack(1, dd->default_factory); - if (args == NULL) - return NULL; - items = PyObject_CallMethod((PyObject *)dd, "items", "()"); - if (items == NULL) { - Py_DECREF(args); - return NULL; - } - iteritems = PyObject_GetIter(items); - Py_DECREF(items); - if (iteritems == NULL) { - Py_DECREF(args); - return NULL; - } - result = PyTuple_Pack(5, dd->dict.ob_type, args, - Py_None, Py_None, iteritems); - Py_DECREF(iteritems); - Py_DECREF(args); - return result; -} - -static PyMethodDef defdict_methods[] = { - {"__missing__", (PyCFunction)defdict_missing, METH_O, - defdict_missing_doc}, - {"copy", (PyCFunction)defdict_copy, METH_NOARGS, - defdict_copy_doc}, - {"__copy__", (PyCFunction)defdict_copy, METH_NOARGS, - defdict_copy_doc}, - {"__reduce__", (PyCFunction)defdict_reduce, METH_NOARGS, - reduce_doc}, - {NULL} -}; - -static PyMemberDef defdict_members[] = { - {"default_factory", T_OBJECT, - offsetof(defdictobject, default_factory), 0, - PyDoc_STR("Factory for default value called by __missing__().")}, - {NULL} -}; - -static void -defdict_dealloc(defdictobject *dd) -{ - Py_CLEAR(dd->default_factory); - PyDict_Type.tp_dealloc((PyObject *)dd); -} - -static int -defdict_print(defdictobject *dd, FILE *fp, int flags) -{ - int sts; - fprintf(fp, "defaultdict("); - if (dd->default_factory == NULL) - fprintf(fp, "None"); - else { - PyObject_Print(dd->default_factory, fp, 0); - } - fprintf(fp, ", "); - sts = PyDict_Type.tp_print((PyObject *)dd, fp, 0); - fprintf(fp, ")"); - return sts; -} - -static PyObject * -defdict_repr(defdictobject *dd) -{ - PyObject *defrepr; - PyObject *baserepr; - PyObject *result; - baserepr = PyDict_Type.tp_repr((PyObject *)dd); - if (baserepr == NULL) - return NULL; - if (dd->default_factory == NULL) - defrepr = PyString_FromString("None"); - else - defrepr = PyObject_Repr(dd->default_factory); - if (defrepr == NULL) { - Py_DECREF(baserepr); - return NULL; - } - result = PyString_FromFormat("defaultdict(%s, %s)", - PyString_AS_STRING(defrepr), - PyString_AS_STRING(baserepr)); - Py_DECREF(defrepr); - Py_DECREF(baserepr); - return result; -} - -static int -defdict_traverse(PyObject *self, visitproc visit, void *arg) -{ - Py_VISIT(((defdictobject *)self)->default_factory); - return PyDict_Type.tp_traverse(self, visit, arg); -} - -static int -defdict_tp_clear(defdictobject *dd) -{ - Py_CLEAR(dd->default_factory); - return PyDict_Type.tp_clear((PyObject *)dd); -} - -static int -defdict_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - defdictobject *dd = (defdictobject *)self; - PyObject *olddefault = dd->default_factory; - PyObject *newdefault = NULL; - PyObject *newargs; - int result; - if (args == NULL || !PyTuple_Check(args)) - newargs = PyTuple_New(0); - else { - Py_ssize_t n = PyTuple_GET_SIZE(args); - if (n > 0) { - newdefault = PyTuple_GET_ITEM(args, 0); - if (!PyCallable_Check(newdefault)) { - PyErr_SetString(PyExc_TypeError, - "first argument must be callable"); - return -1; - } - } - newargs = PySequence_GetSlice(args, 1, n); - } - if (newargs == NULL) - return -1; - Py_XINCREF(newdefault); - dd->default_factory = newdefault; - result = PyDict_Type.tp_init(self, newargs, kwds); - Py_DECREF(newargs); - Py_XDECREF(olddefault); - return result; -} - -PyDoc_STRVAR(defdict_doc, -"defaultdict(default_factory) --> dict with default factory\n\ -\n\ -The default factory is called without arguments to produce\n\ -a new value when a key is not present, in __getitem__ only.\n\ -A defaultdict compares equal to a dict with the same items.\n\ -"); - -/* See comment in xxsubtype.c */ -#define DEFERRED_ADDRESS(ADDR) 0 - -static PyTypeObject defdict_type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, /* ob_size */ - "collections.defaultdict", /* tp_name */ - sizeof(defdictobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)defdict_dealloc, /* tp_dealloc */ - (printfunc)defdict_print, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc)defdict_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 | - Py_TPFLAGS_HAVE_GC, /* tp_flags */ - defdict_doc, /* tp_doc */ - defdict_traverse, /* tp_traverse */ - (inquiry)defdict_tp_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset*/ - 0, /* tp_iter */ - 0, /* tp_iternext */ - defdict_methods, /* tp_methods */ - defdict_members, /* tp_members */ - 0, /* tp_getset */ - DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - defdict_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - 0, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - -/* module level code ********************************************************/ - -PyDoc_STRVAR(module_doc, -"High performance data structures.\n\ -- deque: ordered collection accessible from endpoints only\n\ -- defaultdict: dict subclass with a default value factory\n\ -"); - -PyMODINIT_FUNC -initcollections(void) -{ - PyObject *m; - - m = Py_InitModule3("collections", NULL, module_doc); - if (m == NULL) - return; - - if (PyType_Ready(&deque_type) < 0) - return; - Py_INCREF(&deque_type); - PyModule_AddObject(m, "deque", (PyObject *)&deque_type); - - defdict_type.tp_base = &PyDict_Type; - if (PyType_Ready(&defdict_type) < 0) - return; - Py_INCREF(&defdict_type); - PyModule_AddObject(m, "defaultdict", (PyObject *)&defdict_type); - - if (PyType_Ready(&dequeiter_type) < 0) - return; - - if (PyType_Ready(&dequereviter_type) < 0) - return; - - return; -} Modified: python/branches/p3yk/Modules/datetimemodule.c ============================================================================== --- python/branches/p3yk/Modules/datetimemodule.c (original) +++ python/branches/p3yk/Modules/datetimemodule.c Fri Apr 27 21:54:29 2007 @@ -3644,6 +3644,12 @@ return NULL; fraction = timestamp - (double)timet; us = (int)round_to_long(fraction * 1e6); + if (us < 0) { + /* Truncation towards zero is not what we wanted + for negative numbers (Python's mod semantics) */ + timet -= 1; + us += 1000000; + } /* If timestamp is less than one microsecond smaller than a * full second, round up. Otherwise, ValueErrors are raised * for some floats. */ Modified: python/branches/p3yk/Modules/getpath.c ============================================================================== --- python/branches/p3yk/Modules/getpath.c (original) +++ python/branches/p3yk/Modules/getpath.c Fri Apr 27 21:54:29 2007 @@ -26,7 +26,7 @@ * as best as is possible, but most imports will fail. * * Before any searches are done, the location of the executable is - * determined. If argv[0] has one or more slashs in it, it is used + * determined. If argv[0] has one or more slashes in it, it is used * unchanged. Otherwise, it must have been invoked from the shell's path, * so we search $PATH for the named executable and use that. If the * executable was not found on $PATH (or there was no $PATH environment Modified: python/branches/p3yk/Modules/main.c ============================================================================== --- python/branches/p3yk/Modules/main.c (original) +++ python/branches/p3yk/Modules/main.c Fri Apr 27 21:54:29 2007 @@ -214,13 +214,11 @@ char *module = NULL; FILE *fp = stdin; char *p; - int inspect = 0; int unbuffered = 0; int skipfirstline = 0; int stdin_is_interactive = 0; int help = 0; int version = 0; - int saw_inspect_flag = 0; int saw_unbuffered_flag = 0; PyCompilerFlags cf; @@ -268,8 +266,7 @@ break; case 'i': - inspect++; - saw_inspect_flag = 1; + Py_InspectFlag++; Py_InteractiveFlag++; break; @@ -338,9 +335,9 @@ return 0; } - if (!saw_inspect_flag && + if (!Py_InspectFlag && (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') - inspect = 1; + Py_InspectFlag = 1; if (!saw_unbuffered_flag && (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') unbuffered = 1; @@ -468,7 +465,7 @@ PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind); - if ((inspect || (command == NULL && filename == NULL && module == NULL)) && + if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) && isatty(fileno(stdin))) { PyObject *v; v = PyImport_ImportModule("readline"); @@ -487,6 +484,7 @@ } else { if (filename == NULL && stdin_is_interactive) { + Py_InspectFlag = 0; /* do exit on SystemExit */ RunStartupFile(&cf); } /* XXX */ @@ -499,16 +497,18 @@ /* Check this environment variable at the end, to give programs the * opportunity to set it from Python. */ - if (!saw_inspect_flag && + if (!Py_InspectFlag && (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') { - inspect = 1; + Py_InspectFlag = 1; } - if (inspect && stdin_is_interactive && - (filename != NULL || command != NULL || module != NULL)) + if (Py_InspectFlag && stdin_is_interactive && + (filename != NULL || command != NULL || module != NULL)) { + Py_InspectFlag = 0; /* XXX */ sts = PyRun_AnyFileFlags(stdin, "", &cf) != 0; + } WaitForThreadShutdown(); Modified: python/branches/p3yk/Modules/operator.c ============================================================================== --- python/branches/p3yk/Modules/operator.c (original) +++ python/branches/p3yk/Modules/operator.c Fri Apr 27 21:54:29 2007 @@ -164,43 +164,41 @@ op_getslice(PyObject *s, PyObject *a) { PyObject *a1; - int a2,a3; + Py_ssize_t a2, a3; - if (!PyArg_ParseTuple(a,"Oii:getslice",&a1,&a2,&a3)) + if (!PyArg_ParseTuple(a, "Onn:getslice", &a1, &a2, &a3)) return NULL; - return PySequence_GetSlice(a1,a2,a3); + return PySequence_GetSlice(a1, a2, a3); } static PyObject* op_setslice(PyObject *s, PyObject *a) { PyObject *a1, *a4; - int a2,a3; + Py_ssize_t a2, a3; - if (!PyArg_ParseTuple(a,"OiiO:setslice",&a1,&a2,&a3,&a4)) + if (!PyArg_ParseTuple(a, "OnnO:setslice", &a1, &a2, &a3, &a4)) return NULL; - if (-1 == PySequence_SetSlice(a1,a2,a3,a4)) + if (-1 == PySequence_SetSlice(a1, a2, a3, a4)) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject* op_delslice(PyObject *s, PyObject *a) { PyObject *a1; - int a2,a3; + Py_ssize_t a2, a3; - if(! PyArg_ParseTuple(a,"Oii:delslice",&a1,&a2,&a3)) + if (!PyArg_ParseTuple(a, "Onn:delslice", &a1, &a2, &a3)) return NULL; - if (-1 == PySequence_DelSlice(a1,a2,a3)) + if (-1 == PySequence_DelSlice(a1, a2, a3)) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #undef spam1 Modified: python/branches/p3yk/Modules/posixmodule.c ============================================================================== --- python/branches/p3yk/Modules/posixmodule.c (original) +++ python/branches/p3yk/Modules/posixmodule.c Fri Apr 27 21:54:29 2007 @@ -844,14 +844,48 @@ *(FARPROC*)&gfaxw = GetProcAddress(hKernel32, "GetFileAttributesExW"); } +static BOOL +attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) +{ + HANDLE hFindFile; + WIN32_FIND_DATAA FileData; + hFindFile = FindFirstFileA(pszFile, &FileData); + if (hFindFile == INVALID_HANDLE_VALUE) + return FALSE; + FindClose(hFindFile); + pfad->dwFileAttributes = FileData.dwFileAttributes; + pfad->ftCreationTime = FileData.ftCreationTime; + pfad->ftLastAccessTime = FileData.ftLastAccessTime; + pfad->ftLastWriteTime = FileData.ftLastWriteTime; + pfad->nFileSizeHigh = FileData.nFileSizeHigh; + pfad->nFileSizeLow = FileData.nFileSizeLow; + return TRUE; +} + +static BOOL +attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) +{ + HANDLE hFindFile; + WIN32_FIND_DATAW FileData; + hFindFile = FindFirstFileW(pszFile, &FileData); + if (hFindFile == INVALID_HANDLE_VALUE) + return FALSE; + FindClose(hFindFile); + pfad->dwFileAttributes = FileData.dwFileAttributes; + pfad->ftCreationTime = FileData.ftCreationTime; + pfad->ftLastAccessTime = FileData.ftLastAccessTime; + pfad->ftLastWriteTime = FileData.ftLastWriteTime; + pfad->nFileSizeHigh = FileData.nFileSizeHigh; + pfad->nFileSizeLow = FileData.nFileSizeLow; + return TRUE; +} + static BOOL WINAPI Py_GetFileAttributesExA(LPCSTR pszFile, GET_FILEEX_INFO_LEVELS level, LPVOID pv) { BOOL result; - HANDLE hFindFile; - WIN32_FIND_DATAA FileData; LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv; /* First try to use the system's implementation, if that is available and either succeeds to gives an error other than @@ -873,17 +907,7 @@ accept). */ if (GetFileAttributesA(pszFile) == 0xFFFFFFFF) return FALSE; - hFindFile = FindFirstFileA(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - pfad->dwFileAttributes = FileData.dwFileAttributes; - pfad->ftCreationTime = FileData.ftCreationTime; - pfad->ftLastAccessTime = FileData.ftLastAccessTime; - pfad->ftLastWriteTime = FileData.ftLastWriteTime; - pfad->nFileSizeHigh = FileData.nFileSizeHigh; - pfad->nFileSizeLow = FileData.nFileSizeLow; - return TRUE; + return attributes_from_dir(pszFile, pfad); } static BOOL WINAPI @@ -892,8 +916,6 @@ LPVOID pv) { BOOL result; - HANDLE hFindFile; - WIN32_FIND_DATAW FileData; LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv; /* First try to use the system's implementation, if that is available and either succeeds to gives an error other than @@ -915,17 +937,7 @@ accept). */ if (GetFileAttributesW(pszFile) == 0xFFFFFFFF) return FALSE; - hFindFile = FindFirstFileW(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - pfad->dwFileAttributes = FileData.dwFileAttributes; - pfad->ftCreationTime = FileData.ftCreationTime; - pfad->ftLastAccessTime = FileData.ftLastAccessTime; - pfad->ftLastWriteTime = FileData.ftLastWriteTime; - pfad->nFileSizeHigh = FileData.nFileSizeHigh; - pfad->nFileSizeLow = FileData.nFileSizeLow; - return TRUE; + return attributes_from_dir_w(pszFile, pfad); } static int @@ -936,10 +948,20 @@ char *dot; /* XXX not supported on Win95 and NT 3.x */ if (!Py_GetFileAttributesExA(path, GetFileExInfoStandard, &info)) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; - return -1; + if (GetLastError() != ERROR_SHARING_VIOLATION) { + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; + } else { + /* Could not get attributes on open file. Fall back to + reading the directory. */ + if (!attributes_from_dir(path, &info)) { + /* Very strange. This should not fail now */ + errno = 0; + return -1; + } + } } code = attribute_data_to_stat(&info, result); if (code != 0) @@ -964,10 +986,20 @@ WIN32_FILE_ATTRIBUTE_DATA info; /* XXX not supported on Win95 and NT 3.x */ if (!Py_GetFileAttributesExW(path, GetFileExInfoStandard, &info)) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; - return -1; + if (GetLastError() != ERROR_SHARING_VIOLATION) { + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; + } else { + /* Could not get attributes on open file. Fall back to + reading the directory. */ + if (!attributes_from_dir_w(path, &info)) { + /* Very strange. This should not fail now */ + errno = 0; + return -1; + } + } } code = attribute_data_to_stat(&info, result); if (code < 0) @@ -4809,18 +4841,19 @@ (sizeof(modulepath)/sizeof(modulepath[0])) -strlen(modulepath)); if (stat(modulepath, &statinfo) != 0) { + size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]); /* Eeek - file-not-found - possibly an embedding situation - see if we can locate it in sys.prefix */ strncpy(modulepath, Py_GetExecPrefix(), - sizeof(modulepath)/sizeof(modulepath[0])); + mplen); + modulepath[mplen-1] = '\0'; if (modulepath[strlen(modulepath)-1] != '\\') strcat(modulepath, "\\"); strncat(modulepath, szConsoleSpawn, - (sizeof(modulepath)/sizeof(modulepath[0])) - -strlen(modulepath)); + mplen-strlen(modulepath)); /* No where else to look - raise an easily identifiable error, rather than leaving Windows to report "file not found" - as the user is probably blissfully @@ -6215,16 +6248,23 @@ posix_fdopen(PyObject *self, PyObject *args) { int fd; - char *mode = "r"; + char *orgmode = "r"; int bufsize = -1; FILE *fp; PyObject *f; - if (!PyArg_ParseTuple(args, "i|si", &fd, &mode, &bufsize)) + char *mode; + if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize)) return NULL; - if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') { - PyErr_Format(PyExc_ValueError, - "invalid file mode '%s'", mode); + /* Sanitize mode. See fileobject.c */ + mode = PyMem_MALLOC(strlen(orgmode)+3); + if (!mode) { + PyErr_NoMemory(); + return NULL; + } + strcpy(mode, orgmode); + if (_PyFile_SanitizeMode(mode)) { + PyMem_FREE(mode); return NULL; } Py_BEGIN_ALLOW_THREADS @@ -6245,10 +6285,11 @@ #else fp = fdopen(fd, mode); #endif + PyMem_FREE(mode); Py_END_ALLOW_THREADS if (fp == NULL) return posix_error(); - f = PyFile_FromFile(fp, "", mode, fclose); + f = PyFile_FromFile(fp, "", orgmode, fclose); if (f != NULL) PyFile_SetBufSize(f, bufsize); return f; Modified: python/branches/p3yk/Modules/readline.c ============================================================================== --- python/branches/p3yk/Modules/readline.c (original) +++ python/branches/p3yk/Modules/readline.c Fri Apr 27 21:54:29 2007 @@ -34,6 +34,8 @@ #ifdef HAVE_RL_COMPLETION_MATCHES #define completion_matches(x, y) \ rl_completion_matches((x), ((rl_compentry_func_t *)(y))) +#else +extern char **completion_matches(char *, rl_compentry_func_t *); #endif @@ -632,7 +634,7 @@ /* C function to call the Python completer. */ static char * -on_completion(char *text, int state) +on_completion(const char *text, int state) { char *result = NULL; if (completer != NULL) { Modified: python/branches/p3yk/Modules/socketmodule.c ============================================================================== --- python/branches/p3yk/Modules/socketmodule.c (original) +++ python/branches/p3yk/Modules/socketmodule.c Fri Apr 27 21:54:29 2007 @@ -2384,14 +2384,14 @@ int buflen; /* Get the buffer's memory */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recv", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recv_into", kwlist, &buf, &buflen, &recvlen, &flags)) return NULL; assert(buf != 0 && buflen > 0); if (recvlen < 0) { PyErr_SetString(PyExc_ValueError, - "negative buffersize in recv"); + "negative buffersize in recv_into"); return NULL; } if (recvlen == 0) { @@ -2507,6 +2507,12 @@ if (!PyArg_ParseTuple(args, "i|i:recvfrom", &recvlen, &flags)) return NULL; + if (recvlen < 0) { + PyErr_SetString(PyExc_ValueError, + "negative buffersize in recvfrom"); + return NULL; + } + buf = PyString_FromStringAndSize((char *) 0, recvlen); if (buf == NULL) return NULL; @@ -2553,14 +2559,15 @@ PyObject *addr = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recvfrom", kwlist, - &buf, &buflen, &recvlen, &flags)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recvfrom_into", + kwlist, &buf, &buflen, + &recvlen, &flags)) return NULL; assert(buf != 0 && buflen > 0); if (recvlen < 0) { PyErr_SetString(PyExc_ValueError, - "negative buffersize in recv"); + "negative buffersize in recvfrom_into"); return NULL; } if (recvlen == 0) { Modified: python/branches/p3yk/Modules/timemodule.c ============================================================================== --- python/branches/p3yk/Modules/timemodule.c (original) +++ python/branches/p3yk/Modules/timemodule.c Fri Apr 27 21:54:29 2007 @@ -175,7 +175,8 @@ if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) { /* Unlikely to happen - this works on all intel machines at least! Revert to clock() */ - return PyFloat_FromDouble(clock()); + return PyFloat_FromDouble(((double)clock()) / + CLOCKS_PER_SEC); } divisor = (double)freq.QuadPart; } Modified: python/branches/p3yk/Objects/complexobject.c ============================================================================== --- python/branches/p3yk/Objects/complexobject.c (original) +++ python/branches/p3yk/Objects/complexobject.c Fri Apr 27 21:54:29 2007 @@ -252,12 +252,51 @@ PyComplex_AsCComplex(PyObject *op) { Py_complex cv; + PyObject *newop = NULL; + static PyObject *complex_str = NULL; + + assert(op); + /* If op is already of type PyComplex_Type, return its value */ if (PyComplex_Check(op)) { return ((PyComplexObject *)op)->cval; } + /* If not, use op's __complex__ method, if it exists */ + + /* return -1 on failure */ + cv.real = -1.; + cv.imag = 0.; + + { + PyObject *complexfunc; + if (!complex_str) { + if (!(complex_str = PyString_FromString("__complex__"))) + return cv; + } + complexfunc = _PyType_Lookup(op->ob_type, complex_str); + /* complexfunc is a borrowed reference */ + if (complexfunc) { + newop = PyObject_CallFunctionObjArgs(complexfunc, op, NULL); + if (!newop) + return cv; + } + } + + if (newop) { + if (!PyComplex_Check(newop)) { + PyErr_SetString(PyExc_TypeError, + "__complex__ should return a complex object"); + Py_DECREF(newop); + return cv; + } + cv = ((PyComplexObject *)newop)->cval; + Py_DECREF(newop); + return cv; + } + /* If neither of the above works, interpret op as a float giving the + real part of the result, and fill in the imaginary part as 0. */ else { + /* PyFloat_AsDouble will return -1 on failure */ cv.real = PyFloat_AsDouble(op); - cv.imag = 0.; return cv; } } @@ -512,7 +551,7 @@ } else if (errno == ERANGE) { PyErr_SetString(PyExc_OverflowError, - "complex exponentiaion"); + "complex exponentiation"); return NULL; } return PyComplex_FromCComplex(p); @@ -652,7 +691,7 @@ const char *s, *start; char *end; double x=0.0, y=0.0, z; - int got_re=0, got_im=0, done=0; + int got_re=0, got_im=0, got_bracket=0, done=0; int digit_or_dot; int sw_error=0; int sign; @@ -692,10 +731,17 @@ start = s; while (*s && isspace(Py_CHARMASK(*s))) s++; - if (s[0] == '\0') { + if (s[0] == '\0') { PyErr_SetString(PyExc_ValueError, "complex() arg is an empty string"); return NULL; + } + if (s[0] == '(') { + /* Skip over possible bracket from repr(). */ + got_bracket = 1; + s++; + while (*s && isspace(Py_CHARMASK(*s))) + s++; } z = -1.0; @@ -714,13 +760,26 @@ if(!done) sw_error=1; break; + case ')': + if (!got_bracket || !(got_re || got_im)) { + sw_error=1; + break; + } + got_bracket=0; + done=1; + s++; + while (*s && isspace(Py_CHARMASK(*s))) + s++; + if (*s) sw_error=1; + break; + case '-': sign = -1; /* Fallthrough */ case '+': if (done) sw_error=1; s++; - if ( *s=='\0'||*s=='+'||*s=='-' || + if ( *s=='\0'||*s=='+'||*s=='-'||*s==')'|| isspace(Py_CHARMASK(*s)) ) sw_error=1; break; @@ -746,7 +805,7 @@ if (isspace(Py_CHARMASK(*s))) { while (*s && isspace(Py_CHARMASK(*s))) s++; - if (s[0] != '\0') + if (*s && *s != ')') sw_error=1; else done = 1; @@ -792,7 +851,7 @@ } while (s - start < len && !sw_error); - if (sw_error) { + if (sw_error || got_bracket) { PyErr_SetString(PyExc_ValueError, "complex() arg is a malformed string"); return NULL; @@ -817,12 +876,14 @@ &r, &i)) return NULL; - /* Special-case for single argument that is already complex */ + /* Special-case for a single argument when type(arg) is complex. */ if (PyComplex_CheckExact(r) && i == NULL && type == &PyComplex_Type) { /* Note that we can't know whether it's safe to return a complex *subclass* instance as-is, hence the restriction - to exact complexes here. */ + to exact complexes here. If either the input or the + output is a complex subclass, it will be handled below + as a non-orthogonal vector. */ Py_INCREF(r); return r; } @@ -873,6 +934,14 @@ } return NULL; } + + /* If we get this far, then the "real" and "imag" parts should + both be treated as numbers, and the constructor should return a + complex number equal to (real + imag*1j). + + Note that we do NOT assume the input to already be in canonical + form; the "real" and "imag" parts might themselves be complex + numbers, which slightly complicates the code below. */ if (PyComplex_Check(r)) { /* Note that if r is of a complex subtype, we're only retaining its real & imag parts here, and the return @@ -883,8 +952,14 @@ } } else { + /* The "real" part really is entirely real, and contributes + nothing in the imaginary direction. + Just treat it as a double. */ + cr.imag = 0.0; tmp = PyNumber_Float(r); if (own_r) { + /* r was a newly created complex number, rather + than the original "real" argument. */ Py_DECREF(r); } if (tmp == NULL) @@ -897,7 +972,6 @@ } cr.real = PyFloat_AsDouble(tmp); Py_DECREF(tmp); - cr.imag = 0.0; } if (i == NULL) { ci.real = 0.0; @@ -906,13 +980,19 @@ else if (PyComplex_Check(i)) ci = ((PyComplexObject*)i)->cval; else { + /* The "imag" part really is entirely imaginary, and + contributes nothing in the real direction. + Just treat it as a double. */ + ci.imag = 0.0; tmp = (*nbi->nb_float)(i); if (tmp == NULL) return NULL; ci.real = PyFloat_AsDouble(tmp); Py_DECREF(tmp); - ci.imag = 0.; } + /* If the input was in canonical form, then the "real" and "imag" + parts are real numbers, so that ci.real and cr.imag are zero. + We need this correction in case they were not real numbers. */ cr.real -= ci.imag; cr.imag += ci.real; return complex_subtype_from_c_complex(type, cr); Modified: python/branches/p3yk/Objects/dictobject.c ============================================================================== --- python/branches/p3yk/Objects/dictobject.c (original) +++ python/branches/p3yk/Objects/dictobject.c Fri Apr 27 21:54:29 2007 @@ -1205,6 +1205,24 @@ if (d == NULL) return NULL; + if (PyDict_CheckExact(d) && PyAnySet_CheckExact(seq)) { + dictobject *mp = (dictobject *)d; + Py_ssize_t pos = 0; + PyObject *key; + long hash; + + if (dictresize(mp, PySet_GET_SIZE(seq))) + return NULL; + + while (_PySet_NextEntry(seq, &pos, &key, &hash)) { + Py_INCREF(key); + Py_INCREF(value); + if (insertdict(mp, key, hash, value)) + return NULL; + } + return d; + } + it = PyObject_GetIter(seq); if (it == NULL){ Py_DECREF(d); Modified: python/branches/p3yk/Objects/exceptions.c ============================================================================== --- python/branches/p3yk/Objects/exceptions.c (original) +++ python/branches/p3yk/Objects/exceptions.c Fri Apr 27 21:54:29 2007 @@ -24,6 +24,8 @@ PyBaseExceptionObject *self; self = (PyBaseExceptionObject *)type->tp_alloc(type, 0); + if (!self) + return NULL; /* the dict is created on the fly in PyObject_GenericSetAttr */ self->message = self->dict = NULL; Modified: python/branches/p3yk/Objects/fileobject.c ============================================================================== --- python/branches/p3yk/Objects/fileobject.c (original) +++ python/branches/p3yk/Objects/fileobject.c Fri Apr 27 21:54:29 2007 @@ -138,17 +138,16 @@ ignore stuff they don't understand... write or append mode with universal newline support is expressly forbidden by PEP 278. Additionally, remove the 'U' from the mode string as platforms - won't know what it is. */ -/* zero return is kewl - one is un-kewl */ -static int -sanitize_the_mode(char *mode) + won't know what it is. Non-zero return signals an exception */ +int +_PyFile_SanitizeMode(char *mode) { char *upos; size_t len = strlen(mode); if (!len) { PyErr_SetString(PyExc_ValueError, "empty mode string"); - return 1; + return -1; } upos = strchr(mode, 'U'); @@ -159,7 +158,7 @@ PyErr_Format(PyExc_ValueError, "universal newline " "mode can only be used with modes " "starting with 'r'"); - return 1; + return -1; } if (mode[0] != 'r') { @@ -174,7 +173,7 @@ } else if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') { PyErr_Format(PyExc_ValueError, "mode string must begin with " "one of 'r', 'w', 'a' or 'U', not '%.200s'", mode); - return 1; + return -1; } return 0; @@ -203,7 +202,7 @@ } strcpy(newmode, mode); - if (sanitize_the_mode(newmode)) { + if (_PyFile_SanitizeMode(newmode)) { f = NULL; goto cleanup; } Modified: python/branches/p3yk/Objects/frameobject.c ============================================================================== --- python/branches/p3yk/Objects/frameobject.c (original) +++ python/branches/p3yk/Objects/frameobject.c Fri Apr 27 21:54:29 2007 @@ -48,7 +48,7 @@ } /* Setter for f_lineno - you can set f_lineno from within a trace function in - * order to jump to a given line of code, subject to some restrictions. Most + * order to jump to a given line of code, subject to some restrictions. Most * lines are OK to jump to because they don't make any assumptions about the * state of the stack (obvious because you could remove the line and the code * would still work without any stack errors), but there are some constructs @@ -68,7 +68,7 @@ int new_lineno = 0; /* The new value of f_lineno */ int new_lasti = 0; /* The new value of f_lasti */ int new_iblock = 0; /* The new value of f_iblock */ - char *code = NULL; /* The bytecode for the frame... */ + unsigned char *code = NULL; /* The bytecode for the frame... */ Py_ssize_t code_len = 0; /* ...and its length */ char *lnotab = NULL; /* Iterating over co_lnotab */ Py_ssize_t lnotab_len = 0; /* (ditto) */ @@ -85,7 +85,7 @@ int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */ int in_finally[CO_MAXBLOCKS]; /* (ditto) */ int blockstack_top = 0; /* (ditto) */ - int setup_op = 0; /* (ditto) */ + unsigned char setup_op = 0; /* (ditto) */ /* f_lineno must be an integer. */ if (!PyInt_CheckExact(p_new_lineno)) { @@ -137,7 +137,7 @@ } /* We're now ready to look at the bytecode. */ - PyString_AsStringAndSize(f->f_code->co_code, &code, &code_len); + PyString_AsStringAndSize(f->f_code->co_code, (char **)&code, &code_len); min_addr = MIN(new_lasti, f->f_lasti); max_addr = MAX(new_lasti, f->f_lasti); @@ -159,7 +159,7 @@ /* You can't jump into or out of a 'finally' block because the 'try' * block leaves something on the stack for the END_FINALLY to clean - * up. So we walk the bytecode, maintaining a simulated blockstack. + * up. So we walk the bytecode, maintaining a simulated blockstack. * When we reach the old or new address and it's in a 'finally' block * we note the address of the corresponding SETUP_FINALLY. The jump * is only legal if neither address is in a 'finally' block or @@ -383,7 +383,7 @@ ob_type == &Frametype f_back next item on free list, or NULL f_stacksize size of value stack - ob_size size of localsplus + ob_size size of localsplus Note that the value and block stacks are preserved -- this can save another malloc() call or two (and two free() calls as well!). Also note that, unlike for integers, each frame object is a @@ -408,12 +408,12 @@ PyObject **p, **valuestack; PyCodeObject *co; - PyObject_GC_UnTrack(f); + PyObject_GC_UnTrack(f); Py_TRASHCAN_SAFE_BEGIN(f) /* Kill all local variables */ - valuestack = f->f_valuestack; - for (p = f->f_localsplus; p < valuestack; p++) - Py_CLEAR(*p); + valuestack = f->f_valuestack; + for (p = f->f_localsplus; p < valuestack; p++) + Py_CLEAR(*p); /* Free stack */ if (f->f_stacktop != NULL) { @@ -430,18 +430,18 @@ Py_CLEAR(f->f_exc_value); Py_CLEAR(f->f_exc_traceback); - co = f->f_code; - if (co->co_zombieframe == NULL) - co->co_zombieframe = f; + co = f->f_code; + if (co->co_zombieframe == NULL) + co->co_zombieframe = f; else if (numfree < MAXFREELIST) { ++numfree; f->f_back = free_list; free_list = f; - } + } else PyObject_GC_Del(f); - Py_DECREF(co); + Py_DECREF(co); Py_TRASHCAN_SAFE_END(f) } @@ -482,12 +482,12 @@ int i, slots; /* Before anything else, make sure that this frame is clearly marked - * as being defunct! Else, e.g., a generator reachable from this - * frame may also point to this frame, believe itself to still be - * active, and try cleaning up this frame again. - */ + * as being defunct! Else, e.g., a generator reachable from this + * frame may also point to this frame, believe itself to still be + * active, and try cleaning up this frame again. + */ oldtop = f->f_stacktop; - f->f_stacktop = NULL; + f->f_stacktop = NULL; Py_CLEAR(f->f_exc_type); Py_CLEAR(f->f_exc_value); @@ -514,10 +514,10 @@ "frame", sizeof(PyFrameObject), sizeof(PyObject *), - (destructor)frame_dealloc, /* tp_dealloc */ + (destructor)frame_dealloc, /* tp_dealloc */ 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ @@ -530,8 +530,8 @@ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)frame_traverse, /* tp_traverse */ + 0, /* tp_doc */ + (traverseproc)frame_traverse, /* tp_traverse */ (inquiry)frame_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -579,7 +579,7 @@ builtins = NULL; } if (builtins == NULL) { - /* No builtins! Make up a minimal one + /* No builtins! Make up a minimal one Give them 'None', at least. */ builtins = PyDict_New(); if (builtins == NULL || @@ -599,39 +599,39 @@ Py_INCREF(builtins); } if (code->co_zombieframe != NULL) { - f = code->co_zombieframe; - code->co_zombieframe = NULL; - _Py_NewReference((PyObject *)f); - assert(f->f_code == code); - } - else { - Py_ssize_t extras, ncells, nfrees; - ncells = PyTuple_GET_SIZE(code->co_cellvars); - nfrees = PyTuple_GET_SIZE(code->co_freevars); - extras = code->co_stacksize + code->co_nlocals + ncells + - nfrees; - if (free_list == NULL) { - f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, - extras); - if (f == NULL) { - Py_DECREF(builtins); - return NULL; - } - } - else { - assert(numfree > 0); - --numfree; - f = free_list; - free_list = free_list->f_back; - if (f->ob_size < extras) { - f = PyObject_GC_Resize(PyFrameObject, f, extras); - if (f == NULL) { - Py_DECREF(builtins); - return NULL; - } - } - _Py_NewReference((PyObject *)f); - } + f = code->co_zombieframe; + code->co_zombieframe = NULL; + _Py_NewReference((PyObject *)f); + assert(f->f_code == code); + } + else { + Py_ssize_t extras, ncells, nfrees; + ncells = PyTuple_GET_SIZE(code->co_cellvars); + nfrees = PyTuple_GET_SIZE(code->co_freevars); + extras = code->co_stacksize + code->co_nlocals + ncells + + nfrees; + if (free_list == NULL) { + f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, + extras); + if (f == NULL) { + Py_DECREF(builtins); + return NULL; + } + } + else { + assert(numfree > 0); + --numfree; + f = free_list; + free_list = free_list->f_back; + if (f->ob_size < extras) { + f = PyObject_GC_Resize(PyFrameObject, f, extras); + if (f == NULL) { + Py_DECREF(builtins); + return NULL; + } + } + _Py_NewReference((PyObject *)f); + } f->f_code = code; extras = code->co_nlocals + ncells + nfrees; @@ -640,7 +640,7 @@ f->f_localsplus[i] = NULL; f->f_locals = NULL; f->f_trace = NULL; - f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL; + f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL; } f->f_stacktop = f->f_valuestack; f->f_builtins = builtins; @@ -659,13 +659,13 @@ Py_DECREF(f); return NULL; } - f->f_locals = locals; + f->f_locals = locals; } else { if (locals == NULL) locals = globals; Py_INCREF(locals); - f->f_locals = locals; + f->f_locals = locals; } f->f_tstate = tstate; @@ -701,18 +701,38 @@ return b; } -/* Convert between "fast" version of locals and dictionary version */ +/* Convert between "fast" version of locals and dictionary version. + + map and values are input arguments. map is a tuple of strings. + values is an array of PyObject*. At index i, map[i] is the name of + the variable with value values[i]. The function copies the first + nmap variable from map/values into dict. If values[i] is NULL, + the variable is deleted from dict. + + If deref is true, then the values being copied are cell variables + and the value is extracted from the cell variable before being put + in dict. + + Exceptions raised while modifying the dict are silently ignored, + because there is no good way to report them. + */ static void map_to_dict(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values, - Py_ssize_t deref) + int deref) { Py_ssize_t j; + assert(PyTuple_Check(map)); + assert(PyDict_Check(dict)); + assert(PyTuple_Size(map) >= nmap); for (j = nmap; --j >= 0; ) { PyObject *key = PyTuple_GET_ITEM(map, j); PyObject *value = values[j]; - if (deref) + assert(PyString_Check(key)); + if (deref) { + assert(PyCell_Check(value)); value = PyCell_GET(value); + } if (value == NULL) { if (PyObject_DelItem(dict, key) != 0) PyErr_Clear(); @@ -724,29 +744,55 @@ } } +/* Copy values from the "locals" dict into the fast locals. + + dict is an input argument containing string keys representing + variables names and arbitrary PyObject* as values. + + map and values are input arguments. map is a tuple of strings. + values is an array of PyObject*. At index i, map[i] is the name of + the variable with value values[i]. The function copies the first + nmap variable from map/values into dict. If values[i] is NULL, + the variable is deleted from dict. + + If deref is true, then the values being copied are cell variables + and the value is extracted from the cell variable before being put + in dict. If clear is true, then variables in map but not in dict + are set to NULL in map; if clear is false, variables missing in + dict are ignored. + + Exceptions raised while modifying the dict are silently ignored, + because there is no good way to report them. +*/ + static void dict_to_map(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values, - Py_ssize_t deref, int clear) + int deref, int clear) { Py_ssize_t j; + assert(PyTuple_Check(map)); + assert(PyDict_Check(dict)); + assert(PyTuple_Size(map) >= nmap); for (j = nmap; --j >= 0; ) { PyObject *key = PyTuple_GET_ITEM(map, j); PyObject *value = PyObject_GetItem(dict, key); - if (value == NULL) + assert(PyString_Check(key)); + /* We only care about NULLs if clear is true. */ + if (value == NULL) { PyErr_Clear(); + if (!clear) + continue; + } if (deref) { - if (value || clear) { - if (PyCell_GET(values[j]) != value) { - if (PyCell_Set(values[j], value) < 0) - PyErr_Clear(); - } - } - } else if (value != NULL || clear) { - if (values[j] != value) { - Py_XINCREF(value); - Py_XDECREF(values[j]); - values[j] = value; + assert(PyCell_Check(values[j])); + if (PyCell_GET(values[j]) != value) { + if (PyCell_Set(values[j], value) < 0) + PyErr_Clear(); } + } else if (values[j] != value) { + Py_XINCREF(value); + Py_XDECREF(values[j]); + values[j] = value; } Py_XDECREF(value); } @@ -761,7 +807,7 @@ PyObject *error_type, *error_value, *error_traceback; PyCodeObject *co; Py_ssize_t j; - int ncells, nfreevars; + int ncells, nfreevars; if (f == NULL) return; locals = f->f_locals; @@ -788,8 +834,18 @@ if (ncells || nfreevars) { map_to_dict(co->co_cellvars, ncells, locals, fast + co->co_nlocals, 1); - map_to_dict(co->co_freevars, nfreevars, - locals, fast + co->co_nlocals + ncells, 1); + /* If the namespace is unoptimized, then one of the + following cases applies: + 1. It does not contain free variables, because it + uses import * or is a top-level namespace. + 2. It is a class namespace. + We don't want to accidentally copy free variables + into the locals dict used by the class. + */ + if (co->co_flags & CO_OPTIMIZED) { + map_to_dict(co->co_freevars, nfreevars, + locals, fast + co->co_nlocals + ncells, 1); + } } PyErr_Restore(error_type, error_value, error_traceback); } @@ -827,7 +883,7 @@ locals, fast + co->co_nlocals, 1, clear); dict_to_map(co->co_freevars, nfreevars, locals, fast + co->co_nlocals + ncells, 1, - clear); + clear); } PyErr_Restore(error_type, error_value, error_traceback); } Modified: python/branches/p3yk/Objects/longobject.c ============================================================================== --- python/branches/p3yk/Objects/longobject.c (original) +++ python/branches/p3yk/Objects/longobject.c Fri Apr 27 21:54:29 2007 @@ -1985,6 +1985,8 @@ a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) { /* |a| < |b|. */ *pdiv = (PyLongObject*)PyLong_FromLong(0); + if (*pdiv == NULL) + return -1; Py_INCREF(a); *prem = (PyLongObject *) a; return 0; @@ -1995,6 +1997,10 @@ if (z == NULL) return -1; *prem = (PyLongObject *) PyLong_FromLong((long)rem); + if (*prem == NULL) { + Py_DECREF(z); + return -1; + } } else { z = x_divrem(a, b, prem); @@ -3514,16 +3520,23 @@ if (base == -909) return PyNumber_Long(x); else if (PyString_Check(x)) { - char *s = PyString_AS_STRING(x); - char *end; - PyObject *r = PyLong_FromString(s, &end, base); - if (r != NULL && end != s + PyString_GET_SIZE(x)) { - PyErr_SetString(PyExc_ValueError, - "null byte in argument for int()"); - Py_DECREF(r); - r = NULL; + /* Since PyLong_FromString doesn't have a length parameter, + * check here for possible NULs in the string. */ + char *string = PyString_AS_STRING(x); + if (strlen(string) != PyString_Size(x)) { + /* create a repr() of the input string, + * just like PyLong_FromString does. */ + PyObject *srepr; + srepr = PyObject_Repr(x); + if (srepr == NULL) + return NULL; + PyErr_Format(PyExc_ValueError, + "invalid literal for int() with base %d: %s", + base, PyString_AS_STRING(srepr)); + Py_DECREF(srepr); + return NULL; } - return r; + return PyLong_FromString(PyString_AS_STRING(x), NULL, base); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(x)) Modified: python/branches/p3yk/Objects/setobject.c ============================================================================== --- python/branches/p3yk/Objects/setobject.c (original) +++ python/branches/p3yk/Objects/setobject.c Fri Apr 27 21:54:29 2007 @@ -2154,7 +2154,7 @@ } int -_PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **entry) +_PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **key) { setentry *entry_ptr; @@ -2164,7 +2164,23 @@ } if (set_next((PySetObject *)set, pos, &entry_ptr) == 0) return 0; - *entry = entry_ptr->key; + *key = entry_ptr->key; + return 1; +} + +int +_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash) +{ + setentry *entry; + + if (!PyAnySet_Check(set)) { + PyErr_BadInternalCall(); + return -1; + } + if (set_next((PySetObject *)set, pos, &entry) == 0) + return 0; + *key = entry->key; + *hash = entry->hash; return 1; } Modified: python/branches/p3yk/Objects/sliceobject.c ============================================================================== --- python/branches/p3yk/Objects/sliceobject.c (original) +++ python/branches/p3yk/Objects/sliceobject.c Fri Apr 27 21:54:29 2007 @@ -274,9 +274,19 @@ S. Out of bounds indices are clipped in a manner consistent with the\n\ handling of normal slices."); +static PyObject * +slice_reduce(PySliceObject* self) +{ + return Py_BuildValue("O(OOO)", self->ob_type, self->start, self->stop, self->step); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + static PyMethodDef slice_methods[] = { {"indices", (PyCFunction)slice_indices, METH_O, slice_indices_doc}, + {"__reduce__", (PyCFunction)slice_reduce, + METH_NOARGS, reduce_doc}, {NULL, NULL} }; Modified: python/branches/p3yk/Objects/stringobject.c ============================================================================== --- python/branches/p3yk/Objects/stringobject.c (original) +++ python/branches/p3yk/Objects/stringobject.c Fri Apr 27 21:54:29 2007 @@ -2346,10 +2346,10 @@ string_translate(PyStringObject *self, PyObject *args) { register char *input, *output; - register const char *table; + const char *table; register Py_ssize_t i, c, changed = 0; PyObject *input_obj = (PyObject*)self; - const char *table1, *output_start, *del_table=NULL; + const char *output_start, *del_table=NULL; Py_ssize_t inlen, tablen, dellen = 0; PyObject *result; int trans_table[256]; @@ -2360,9 +2360,13 @@ return NULL; if (PyString_Check(tableobj)) { - table1 = PyString_AS_STRING(tableobj); + table = PyString_AS_STRING(tableobj); tablen = PyString_GET_SIZE(tableobj); } + else if (tableobj == Py_None) { + table = NULL; + tablen = 256; + } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(tableobj)) { /* Unicode .translate() does not support the deletechars @@ -2376,7 +2380,7 @@ return PyUnicode_Translate((PyObject *)self, tableobj, NULL); } #endif - else if (PyObject_AsCharBuffer(tableobj, &table1, &tablen)) + else if (PyObject_AsCharBuffer(tableobj, &table, &tablen)) return NULL; if (tablen != 256) { @@ -2405,7 +2409,6 @@ dellen = 0; } - table = table1; inlen = PyString_GET_SIZE(input_obj); result = PyString_FromStringAndSize((char *)NULL, inlen); if (result == NULL) @@ -2413,7 +2416,7 @@ output_start = output = PyString_AsString(result); input = PyString_AS_STRING(input_obj); - if (dellen == 0) { + if (dellen == 0 && table != NULL) { /* If no deletions are required, use faster code */ for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); @@ -2427,8 +2430,13 @@ return input_obj; } - for (i = 0; i < 256; i++) - trans_table[i] = Py_CHARMASK(table[i]); + if (table == NULL) { + for (i = 0; i < 256; i++) + trans_table[i] = Py_CHARMASK(i); + } else { + for (i = 0; i < 256; i++) + trans_table[i] = Py_CHARMASK(table[i]); + } for (i = 0; i < dellen; i++) trans_table[(int) Py_CHARMASK(del_table[i])] = -1; Modified: python/branches/p3yk/Objects/typeobject.c ============================================================================== --- python/branches/p3yk/Objects/typeobject.c (original) +++ python/branches/p3yk/Objects/typeobject.c Fri Apr 27 21:54:29 2007 @@ -265,9 +265,10 @@ PyObject* mro; PyArg_UnpackTuple(PyList_GET_ITEM(temp, i), "", 2, 2, &cls, &mro); - Py_DECREF(cls->tp_mro); + Py_INCREF(mro); + ob = cls->tp_mro; cls->tp_mro = mro; - Py_INCREF(cls->tp_mro); + Py_DECREF(ob); } Py_DECREF(temp); goto bail; @@ -520,7 +521,7 @@ if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) /* For a heaptype, the instances count as references - to the type. Traverse the type so the collector + to the type. Traverse the type so the collector can find cycles involving this link. */ Py_VISIT(type); @@ -640,7 +641,7 @@ assert(base); } - /* If we added a weaklist, we clear it. Do this *before* calling + /* If we added a weaklist, we clear it. Do this *before* calling the finalizer (__del__), clearing slots, or clearing the instance dict. */ @@ -711,7 +712,7 @@ A. Read the comment titled "Trashcan mechanism" in object.h. For one, this explains why there must be a call to GC-untrack - before the trashcan begin macro. Without understanding the + before the trashcan begin macro. Without understanding the trashcan code, the answers to the following questions don't make sense. @@ -719,7 +720,7 @@ GC-track again afterward? A. In the case that the base class is GC-aware, the base class - probably GC-untracks the object. If it does that using the + probably GC-untracks the object. If it does that using the UNTRACK macro, this will crash when the object is already untracked. Because we don't know what the base class does, the only safe thing is to make sure the object is tracked when we @@ -727,19 +728,19 @@ requires that the object is *untracked* before it is called. So the dance becomes: - GC untrack + GC untrack trashcan begin GC track - Q. Why did the last question say "immediately GC-track again"? - It's nowhere near immediately. + Q. Why did the last question say "immediately GC-track again"? + It's nowhere near immediately. - A. Because the code *used* to re-track immediately. Bad Idea. - self has a refcount of 0, and if gc ever gets its hands on it - (which can happen if any weakref callback gets invoked), it - looks like trash to gc too, and gc also tries to delete self - then. But we're already deleting self. Double dealloction is - a subtle disaster. + A. Because the code *used* to re-track immediately. Bad Idea. + self has a refcount of 0, and if gc ever gets its hands on it + (which can happen if any weakref callback gets invoked), it + looks like trash to gc too, and gc also tries to delete self + then. But we're already deleting self. Double dealloction is + a subtle disaster. Q. Why the bizarre (net-zero) manipulation of _PyTrash_delete_nesting around the trashcan macros? @@ -752,17 +753,17 @@ - subtype_dealloc() is called - the trashcan limit is not yet reached, so the trashcan level - is incremented and the code between trashcan begin and end is - executed + is incremented and the code between trashcan begin and end is + executed - this destroys much of the object's contents, including its - slots and __dict__ + slots and __dict__ - basedealloc() is called; this is really list_dealloc(), or - some other type which also uses the trashcan macros + some other type which also uses the trashcan macros - the trashcan limit is now reached, so the object is put on the - trashcan's to-be-deleted-later list + trashcan's to-be-deleted-later list - basedealloc() returns @@ -771,13 +772,13 @@ - subtype_dealloc() returns - later, the trashcan code starts deleting the objects from its - to-be-deleted-later list + to-be-deleted-later list - subtype_dealloc() is called *AGAIN* for the same object - at the very least (if the destroyed slots and __dict__ don't - cause problems) the object's type gets decref'ed a second - time, which is *BAD*!!! + cause problems) the object's type gets decref'ed a second + time, which is *BAD*!!! The remedy is to make sure that if the code between trashcan begin and end in subtype_dealloc() is called, the code between @@ -789,7 +790,7 @@ But now it's possible that a chain of objects consisting solely of objects whose deallocator is subtype_dealloc() will defeat the trashcan mechanism completely: the decremented level means - that the effective level never reaches the limit. Therefore, we + that the effective level never reaches the limit. Therefore, we *increment* the level *before* entering the trashcan block, and matchingly decrement it after leaving. This means the trashcan code will trigger a little early, but that's no big deal. @@ -840,7 +841,7 @@ /* Internal routines to do a method lookup in the type without looking in the instance dictionary (so we can't use PyObject_GetAttr) but still binding - it to the instance. The arguments are the object, + it to the instance. The arguments are the object, the method name as a C string, and the address of a static variable used to cache the interned Python string. @@ -883,7 +884,7 @@ } /* A variation of PyObject_CallMethod that uses lookup_method() - instead of PyObject_GetAttrString(). This uses the same convention + instead of PyObject_GetAttrString(). This uses the same convention as lookup_method to cache the interned name string object. */ static PyObject * @@ -1044,7 +1045,7 @@ It's hard to produce a good error message. In the absence of better insight into error reporting, report the classes that were candidates - to be put next into the MRO. There is some conflict between the + to be put next into the MRO. There is some conflict between the order in which they should be put in the MRO, but it's hard to diagnose what constraint can't be satisfied. */ @@ -1116,7 +1117,7 @@ if (remain[i] >= PyList_GET_SIZE(cur_list)) { empty_cnt++; continue; - } + } /* Choose next candidate for MRO. @@ -1193,7 +1194,7 @@ if (parentMRO == NULL) { Py_DECREF(to_merge); return NULL; - } + } PyList_SET_ITEM(to_merge, i, parentMRO); } @@ -1510,32 +1511,69 @@ static PyObject * _unicode_to_string(PyObject *slots, Py_ssize_t nslots) { - PyObject *tmp = slots; - PyObject *o, *o1; + PyObject *tmp = NULL; + PyObject *slot_name, *new_name; Py_ssize_t i; - ssizessizeargfunc copy = slots->ob_type->tp_as_sequence->sq_slice; + for (i = 0; i < nslots; i++) { - if (PyUnicode_Check(o = PyTuple_GET_ITEM(tmp, i))) { - if (tmp == slots) { - tmp = copy(slots, 0, PyTuple_GET_SIZE(slots)); + if (PyUnicode_Check(slot_name = PyTuple_GET_ITEM(slots, i))) { + if (tmp == NULL) { + tmp = PySequence_List(slots); if (tmp == NULL) return NULL; } - o1 = _PyUnicode_AsDefaultEncodedString - (o, NULL); - if (o1 == NULL) { + new_name = _PyUnicode_AsDefaultEncodedString(slot_name, + NULL); + if (new_name == NULL) { Py_DECREF(tmp); - return 0; + return NULL; } - Py_INCREF(o1); - Py_DECREF(o); - PyTuple_SET_ITEM(tmp, i, o1); + Py_INCREF(new_name); + PyList_SET_ITEM(tmp, i, new_name); + Py_DECREF(slot_name); } } - return tmp; + if (tmp != NULL) { + slots = PyList_AsTuple(tmp); + Py_DECREF(tmp); + } + return slots; } #endif +/* Forward */ +static int +object_init(PyObject *self, PyObject *args, PyObject *kwds); + +static int +type_init(PyObject *cls, PyObject *args, PyObject *kwds) +{ + int res; + + assert(args != NULL && PyTuple_Check(args)); + assert(kwds == NULL || PyDict_Check(kwds)); + + if (kwds != NULL && PyDict_Check(kwds) && PyDict_Size(kwds) != 0) { + PyErr_SetString(PyExc_TypeError, + "type.__init__() takes no keyword arguments"); + return -1; + } + + if (args != NULL && PyTuple_Check(args) && + (PyTuple_GET_SIZE(args) != 1 && PyTuple_GET_SIZE(args) != 3)) { + PyErr_SetString(PyExc_TypeError, + "type.__init__() takes 1 or 3 arguments"); + return -1; + } + + /* Call object.__init__(self) now. */ + /* XXX Could call super(type, cls).__init__() but what's the point? */ + args = PyTuple_GetSlice(args, 0, 0); + res = object_init(cls, args, NULL); + Py_DECREF(args); + return res; +} + static PyObject * type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { @@ -1652,7 +1690,7 @@ /* Have slots */ /* Make it into a tuple */ - if (PyString_Check(slots)) + if (PyString_Check(slots) || PyUnicode_Check(slots)) slots = PyTuple_Pack(1, slots); else slots = PySequence_Tuple(slots); @@ -1677,12 +1715,12 @@ #ifdef Py_USING_UNICODE tmp = _unicode_to_string(slots, nslots); + if (tmp == NULL) + goto bad_slots; if (tmp != slots) { Py_DECREF(slots); slots = tmp; } - if (!tmp) - return NULL; #endif /* Check for valid slot names and two special cases */ for (i = 0; i < nslots; i++) { @@ -1713,8 +1751,11 @@ } } - /* Copy slots into yet another tuple, demangling names */ - newslots = PyTuple_New(nslots - add_dict - add_weak); + /* Copy slots into a list, mangle names and sort them. + Sorted names are needed for __class__ assignment. + Convert them back to tuple at the end. + */ + newslots = PyList_New(nslots - add_dict - add_weak); if (newslots == NULL) goto bad_slots; for (i = j = 0; i < nslots; i++) { @@ -1725,15 +1766,25 @@ (add_weak && strcmp(s, "__weakref__") == 0)) continue; tmp =_Py_Mangle(name, tmp); - if (!tmp) - goto bad_slots; - PyTuple_SET_ITEM(newslots, j, tmp); + if (!tmp) + goto bad_slots; + PyList_SET_ITEM(newslots, j, tmp); j++; } assert(j == nslots - add_dict - add_weak); nslots = j; Py_DECREF(slots); - slots = newslots; + if (PyList_Sort(newslots) == -1) { + Py_DECREF(bases); + Py_DECREF(newslots); + return NULL; + } + slots = PyList_AsTuple(newslots); + Py_DECREF(newslots); + if (slots == NULL) { + Py_DECREF(bases); + return NULL; + } /* Secondary bases may provide weakrefs or dict */ if (nbases > 1 && @@ -1824,13 +1875,13 @@ PyObject *doc = PyDict_GetItemString(dict, "__doc__"); if (doc != NULL && PyString_Check(doc)) { const size_t n = (size_t)PyString_GET_SIZE(doc); - char *tp_doc = (char *)PyObject_MALLOC(n+1); + char *tp_doc = (char *)PyObject_MALLOC(n+1); if (tp_doc == NULL) { Py_DECREF(type); return NULL; } memcpy(tp_doc, PyString_AS_STRING(doc), n+1); - type->tp_doc = tp_doc; + type->tp_doc = tp_doc; } } @@ -1856,13 +1907,11 @@ PyTuple_GET_ITEM(slots, i)); mp->type = T_OBJECT_EX; mp->offset = slotoffset; - if (base->tp_weaklistoffset == 0 && - strcmp(mp->name, "__weakref__") == 0) { - add_weak++; - mp->type = T_OBJECT; - mp->flags = READONLY; - type->tp_weaklistoffset = slotoffset; - } + + /* __dict__ and __weakref__ are already filtered out */ + assert(strcmp(mp->name, "__dict__") != 0); + assert(strcmp(mp->name, "__weakref__") != 0); + slotoffset += sizeof(PyObject *); } } @@ -2070,9 +2119,9 @@ Py_XDECREF(type->tp_mro); Py_XDECREF(type->tp_cache); Py_XDECREF(type->tp_subclasses); - /* A type's tp_doc is heap allocated, unlike the tp_doc slots - * of most other objects. It's okay to cast it to char *. - */ + /* A type's tp_doc is heap allocated, unlike the tp_doc slots + * of most other objects. It's okay to cast it to char *. + */ PyObject_Free((char *)type->tp_doc); Py_XDECREF(et->ht_name); Py_XDECREF(et->ht_slots); @@ -2191,7 +2240,7 @@ sizeof(PyMemberDef), /* tp_itemsize */ (destructor)type_dealloc, /* tp_dealloc */ 0, /* tp_print */ - 0, /* tp_getattr */ + 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)type_repr, /* tp_repr */ @@ -2221,37 +2270,113 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ - 0, /* tp_init */ + type_init, /* tp_init */ 0, /* tp_alloc */ type_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + PyObject_GC_Del, /* tp_free */ (inquiry)type_is_gc, /* tp_is_gc */ }; /* The base type of all types (eventually)... except itself. */ +/* You may wonder why object.__new__() only complains about arguments + when object.__init__() is not overridden, and vice versa. + + Consider the use cases: + + 1. When neither is overridden, we want to hear complaints about + excess (i.e., any) arguments, since their presence could + indicate there's a bug. + + 2. When defining an Immutable type, we are likely to override only + __new__(), since __init__() is called too late to initialize an + Immutable object. Since __new__() defines the signature for the + type, it would be a pain to have to override __init__() just to + stop it from complaining about excess arguments. + + 3. When defining a Mutable type, we are likely to override only + __init__(). So here the converse reasoning applies: we don't + want to have to override __new__() just to stop it from + complaining. + + 4. When __init__() is overridden, and the subclass __init__() calls + object.__init__(), the latter should complain about excess + arguments; ditto for __new__(). + + Use cases 2 and 3 make it unattractive to unconditionally check for + excess arguments. The best solution that addresses all four use + cases is as follows: __init__() complains about excess arguments + unless __new__() is overridden and __init__() is not overridden + (IOW, if __init__() is overridden or __new__() is not overridden); + symmetrically, __new__() complains about excess arguments unless + __init__() is overridden and __new__() is not overridden + (IOW, if __new__() is overridden or __init__() is not overridden). + + However, for backwards compatibility, this breaks too much code. + Therefore, in 2.6, we'll *warn* about excess arguments when both + methods are overridden; for all other cases we'll use the above + rules. + +*/ + +/* Forward */ +static PyObject * +object_new(PyTypeObject *type, PyObject *args, PyObject *kwds); + +static int +excess_args(PyObject *args, PyObject *kwds) +{ + return PyTuple_GET_SIZE(args) || + (kwds && PyDict_Check(kwds) && PyDict_Size(kwds)); +} + static int object_init(PyObject *self, PyObject *args, PyObject *kwds) { - return 0; + int err = 0; + if (excess_args(args, kwds)) { + PyTypeObject *type = self->ob_type; + if (type->tp_init != object_init && + type->tp_new != object_new) + { + err = PyErr_WarnEx(PyExc_DeprecationWarning, + "object.__init__() takes no parameters", + 1); + } + else if (type->tp_init != object_init || + type->tp_new == object_new) + { + PyErr_SetString(PyExc_TypeError, + "object.__init__() takes no parameters"); + err = -1; + } + } + return err; } -/* If we don't have a tp_new for a new-style class, new will use this one. - Therefore this should take no arguments/keywords. However, this new may - also be inherited by objects that define a tp_init but no tp_new. These - objects WILL pass argumets to tp_new, because it gets the same args as - tp_init. So only allow arguments if we aren't using the default init, in - which case we expect init to handle argument parsing. */ static PyObject * object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - if (type->tp_init == object_init && (PyTuple_GET_SIZE(args) || - (kwds && PyDict_Check(kwds) && PyDict_Size(kwds)))) { - PyErr_SetString(PyExc_TypeError, - "default __new__ takes no parameters"); - return NULL; + int err = 0; + if (excess_args(args, kwds)) { + if (type->tp_new != object_new && + type->tp_init != object_init) + { + err = PyErr_WarnEx(PyExc_DeprecationWarning, + "object.__new__() takes no parameters", + 1); + } + else if (type->tp_new != object_new || + type->tp_init == object_init) + { + PyErr_SetString(PyExc_TypeError, + "object.__new__() takes no parameters"); + err = -1; + } } + if (err < 0) + return NULL; return type->tp_alloc(type, 0); } @@ -2368,6 +2493,7 @@ { PyTypeObject *base = a->tp_base; Py_ssize_t size; + PyObject *slots_a, *slots_b; if (base != b->tp_base) return 0; @@ -2378,6 +2504,15 @@ size += sizeof(PyObject *); if (a->tp_weaklistoffset == size && b->tp_weaklistoffset == size) size += sizeof(PyObject *); + + /* Check slots compliance */ + slots_a = ((PyHeapTypeObject *)a)->ht_slots; + slots_b = ((PyHeapTypeObject *)b)->ht_slots; + if (slots_a && slots_b) { + if (PyObject_Compare(slots_a, slots_b) != 0) + return 0; + size += sizeof(PyObject *) * PyTuple_GET_SIZE(slots_a); + } return size == a->tp_basicsize && size == b->tp_basicsize; } @@ -2661,11 +2796,54 @@ return res; } +/* + * There were two problems when object.__reduce__ and object.__reduce_ex__ + * were implemented in the same function: + * - trying to pickle an object with a custom __reduce__ method that + * fell back to object.__reduce__ in certain circumstances led to + * infinite recursion at Python level and eventual RuntimeError. + * - Pickling objects that lied about their type by overwriting the + * __class__ descriptor could lead to infinite recursion at C level + * and eventual segfault. + * + * Because of backwards compatibility, the two methods still have to + * behave in the same way, even if this is not required by the pickle + * protocol. This common functionality was moved to the _common_reduce + * function. + */ +static PyObject * +_common_reduce(PyObject *self, int proto) +{ + PyObject *copy_reg, *res; + + if (proto >= 2) + return reduce_2(self); + + copy_reg = import_copy_reg(); + if (!copy_reg) + return NULL; + + res = PyEval_CallMethod(copy_reg, "_reduce_ex", "(Oi)", self, proto); + Py_DECREF(copy_reg); + + return res; +} + +static PyObject * +object_reduce(PyObject *self, PyObject *args) +{ + int proto = 0; + + if (!PyArg_ParseTuple(args, "|i:__reduce__", &proto)) + return NULL; + + return _common_reduce(self, proto); +} + static PyObject * object_reduce_ex(PyObject *self, PyObject *args) { - /* Call copy_reg._reduce_ex(self, proto) */ - PyObject *reduce, *copy_reg, *res; + PyObject *reduce, *res; int proto = 0; if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto)) @@ -2701,23 +2879,13 @@ Py_DECREF(reduce); } - if (proto >= 2) - return reduce_2(self); - - copy_reg = import_copy_reg(); - if (!copy_reg) - return NULL; - - res = PyEval_CallMethod(copy_reg, "_reduce_ex", "(Oi)", self, proto); - Py_DECREF(copy_reg); - - return res; + return _common_reduce(self, proto); } static PyMethodDef object_methods[] = { {"__reduce_ex__", object_reduce_ex, METH_VARARGS, PyDoc_STR("helper for pickle")}, - {"__reduce__", object_reduce_ex, METH_VARARGS, + {"__reduce__", object_reduce, METH_VARARGS, PyDoc_STR("helper for pickle")}, {0} }; @@ -2725,13 +2893,13 @@ PyTypeObject PyBaseObject_Type = { PyObject_HEAD_INIT(&PyType_Type) - 0, /* ob_size */ + 0, /* ob_size */ "object", /* tp_name */ sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */ object_dealloc, /* tp_dealloc */ 0, /* tp_print */ - 0, /* tp_getattr */ + 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ object_repr, /* tp_repr */ @@ -2763,7 +2931,7 @@ object_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ object_new, /* tp_new */ - PyObject_Del, /* tp_free */ + PyObject_Del, /* tp_free */ }; @@ -3136,9 +3304,9 @@ Py_INCREF(base); } - /* Now the only way base can still be NULL is if type is - * &PyBaseObject_Type. - */ + /* Now the only way base can still be NULL is if type is + * &PyBaseObject_Type. + */ /* Initialize the base class */ if (base != NULL && base->tp_dict == NULL) { @@ -3146,13 +3314,13 @@ goto error; } - /* Initialize ob_type if NULL. This means extensions that want to be + /* Initialize ob_type if NULL. This means extensions that want to be compilable separately on Windows can call PyType_Ready() instead of initializing the ob_type field of their type objects. */ - /* The test for base != NULL is really unnecessary, since base is only - NULL when type is &PyBaseObject_Type, and we know its ob_type is - not NULL (it's initialized to &PyType_Type). But coverity doesn't - know that. */ + /* The test for base != NULL is really unnecessary, since base is only + NULL when type is &PyBaseObject_Type, and we know its ob_type is + not NULL (it's initialized to &PyType_Type). But coverity doesn't + know that. */ if (type->ob_type == NULL && base != NULL) type->ob_type = base->ob_type; @@ -3216,9 +3384,9 @@ /* Sanity check for tp_free. */ if (PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) && (type->tp_free == NULL || type->tp_free == PyObject_Del)) { - /* This base class needs to call tp_free, but doesn't have - * one, or its tp_free is for non-gc'ed objects. - */ + /* This base class needs to call tp_free, but doesn't have + * one, or its tp_free is for non-gc'ed objects. + */ PyErr_Format(PyExc_TypeError, "type '%.100s' participates in " "gc and is a base type but has inappropriate " "tp_free slot", @@ -3357,7 +3525,7 @@ /* Generic wrappers for overloadable 'operators' such as __getitem__ */ /* There's a wrapper *function* for each distinct function typedef used - for type object slots (e.g. binaryfunc, ternaryfunc, etc.). There's a + for type object slots (e.g. binaryfunc, ternaryfunc, etc.). There's a wrapper *table* for each distinct operation (e.g. __len__, __add__). Most tables have only one entry; the tables for binary operators have two entries, one regular and one with reversed arguments. */ @@ -3692,8 +3860,8 @@ PyTypeObject *type = self->ob_type; while (type && type->tp_flags & Py_TPFLAGS_HEAPTYPE) type = type->tp_base; - /* If type is NULL now, this is a really weird type. - In the spirit of backwards compatibility (?), just shut up. */ + /* If type is NULL now, this is a really weird type. + In the spirit of backwards compatibility (?), just shut up. */ if (type && type->tp_setattro != func) { PyErr_Format(PyExc_TypeError, "can't apply this %s to %s object", @@ -3909,8 +4077,8 @@ staticbase = subtype; while (staticbase && (staticbase->tp_flags & Py_TPFLAGS_HEAPTYPE)) staticbase = staticbase->tp_base; - /* If staticbase is NULL now, it is a really weird type. - In the spirit of backwards compatibility (?), just shut up. */ + /* If staticbase is NULL now, it is a really weird type. + In the spirit of backwards compatibility (?), just shut up. */ if (staticbase && staticbase->tp_new != type->tp_new) { PyErr_Format(PyExc_TypeError, "%s.__new__(%s) is not safe, use %s.__new__()", @@ -3931,7 +4099,7 @@ static struct PyMethodDef tp_new_methoddef[] = { {"__new__", (PyCFunction)tp_new_wrapper, METH_KEYWORDS, PyDoc_STR("T.__new__(S, ...) -> " - "a new object with type S, a subtype of T")}, + "a new object with type S, a subtype of T")}, {0} }; @@ -4869,17 +5037,17 @@ user-defined methods has unexpected side-effects, as shown by test_descr.notimplemented() */ SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc, - "x.__add__(y) <==> x+y"), + "x.__add__(y) <==> x+y"), SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, - "x.__mul__(n) <==> x*n"), + "x.__mul__(n) <==> x*n"), SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, - "x.__rmul__(n) <==> n*x"), + "x.__rmul__(n) <==> n*x"), SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, "x.__getitem__(y) <==> x[y]"), SQSLOT("__getslice__", sq_slice, slot_sq_slice, wrap_ssizessizeargfunc, "x.__getslice__(i, j) <==> x[i:j]\n\ - \n\ - Use of negative indices is not supported."), + \n\ + Use of negative indices is not supported."), SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem, "x.__setitem__(i, y) <==> x[i]=y"), SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem, @@ -4887,18 +5055,18 @@ SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice, wrap_ssizessizeobjargproc, "x.__setslice__(i, j, y) <==> x[i:j]=y\n\ - \n\ - Use of negative indices is not supported."), + \n\ + Use of negative indices is not supported."), SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice, "x.__delslice__(i, j) <==> del x[i:j]\n\ - \n\ - Use of negative indices is not supported."), + \n\ + Use of negative indices is not supported."), SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc, "x.__contains__(y) <==> y in x"), SQSLOT("__iadd__", sq_inplace_concat, NULL, - wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"), + wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"), SQSLOT("__imul__", sq_inplace_repeat, NULL, - wrap_indexargfunc, "x.__imul__(y) <==> x*=y"), + wrap_indexargfunc, "x.__imul__(y) <==> x*=y"), MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc, "x.__len__() <==> len(x)"), @@ -5049,7 +5217,7 @@ }; /* Given a type pointer and an offset gotten from a slotdef entry, return a - pointer to the actual slot. This is not quite the same as simply adding + pointer to the actual slot. This is not quite the same as simply adding the offset to the type pointer, since it takes care to indirect through the proper indirection pointer (as_buffer, etc.); it returns NULL if the indirection pointer is NULL. */ @@ -5113,7 +5281,7 @@ } /* Look in all matching slots of the type; if exactly one of these has - a filled-in slot, return its value. Otherwise return NULL. */ + a filled-in slot, return its value. Otherwise return NULL. */ res = NULL; for (pp = ptrs; *pp; pp++) { ptr = slotptr(type, (*pp)->offset); @@ -5352,13 +5520,13 @@ dictionary with method descriptors for function slots. For each function slot (like tp_repr) that's defined in the type, one or more corresponding descriptors are added in the type's tp_dict dictionary - under the appropriate name (like __repr__). Some function slots + under the appropriate name (like __repr__). Some function slots cause more than one descriptor to be added (for example, the nb_add slot adds both __add__ and __radd__ descriptors) and some function slots compete for the same descriptor (for example both sq_item and mp_subscript generate a __getitem__ descriptor). - In the latter case, the first slotdef entry encoutered wins. Since + In the latter case, the first slotdef entry encoutered wins. Since slotdef entries are sorted by the offset of the slot in the PyHeapTypeObject, this gives us some control over disambiguating between competing slots: the members of PyHeapTypeObject are listed @@ -5530,7 +5698,7 @@ obj can be a new-style class, or an instance of one: - - If it is a class, it must be a subclass of 'type'. This case is + - If it is a class, it must be a subclass of 'type'. This case is used for class methods; the return value is obj. - If it is an instance, it must be an instance of 'type'. This is @@ -5581,7 +5749,7 @@ Py_DECREF(class_attr); } - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_TypeError, "super(type, obj): " "obj must be an instance or subtype of type"); return NULL; @@ -5602,7 +5770,7 @@ /* If su is an instance of a (strict) subclass of super, call its type */ return PyObject_CallFunctionObjArgs((PyObject *)su->ob_type, - su->type, obj, NULL); + su->type, obj, NULL); else { /* Inline the common case */ PyTypeObject *obj_type = supercheck(su->type, obj); @@ -5655,7 +5823,7 @@ "Typical use to call a cooperative superclass method:\n" "class C(B):\n" " def meth(self, arg):\n" -" super(C, self).meth(arg)"); +" super(C, self).meth(arg)"); static int super_traverse(PyObject *self, visitproc visit, void *arg) @@ -5676,7 +5844,7 @@ sizeof(superobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - super_dealloc, /* tp_dealloc */ + super_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -5684,7 +5852,7 @@ super_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ + 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ @@ -5693,9 +5861,9 @@ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ - super_doc, /* tp_doc */ - super_traverse, /* tp_traverse */ - 0, /* tp_clear */ + super_doc, /* tp_doc */ + super_traverse, /* tp_traverse */ + 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ @@ -5711,5 +5879,5 @@ super_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + PyObject_GC_Del, /* tp_free */ }; Modified: python/branches/p3yk/PC/VC6/pcbuild.dsw ============================================================================== --- python/branches/p3yk/PC/VC6/pcbuild.dsw (original) +++ python/branches/p3yk/PC/VC6/pcbuild.dsw Fri Apr 27 21:54:29 2007 @@ -26,6 +26,9 @@ Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name pythoncore + End Project Dependency }}} ############################################################################### Modified: python/branches/p3yk/PC/_winreg.c ============================================================================== --- python/branches/p3yk/PC/_winreg.c (original) +++ python/branches/p3yk/PC/_winreg.c Fri Apr 27 21:54:29 2007 @@ -697,7 +697,7 @@ case REG_DWORD: if (value != Py_None && !PyInt_Check(value)) return FALSE; - *retDataBuf = (BYTE *)PyMem_NEW(DWORD, sizeof(DWORD)); + *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1); if (*retDataBuf==NULL){ PyErr_NoMemory(); return FALSE; Modified: python/branches/p3yk/PC/config.c ============================================================================== --- python/branches/p3yk/PC/config.c (original) +++ python/branches/p3yk/PC/config.c Fri Apr 27 21:54:29 2007 @@ -43,7 +43,7 @@ extern void initzipimport(void); extern void init_random(void); extern void inititertools(void); -extern void initcollections(void); +extern void init_collections(void); extern void init_heapq(void); extern void init_bisect(void); extern void init_symtable(void); @@ -126,7 +126,7 @@ {"_heapq", init_heapq}, {"_lsprof", init_lsprof}, {"itertools", inititertools}, - {"collections", initcollections}, + {"_collections", init_collections}, {"_symtable", init_symtable}, {"mmap", initmmap}, {"_csv", init_csv}, Modified: python/branches/p3yk/PC/getpathp.c ============================================================================== --- python/branches/p3yk/PC/getpathp.c (original) +++ python/branches/p3yk/PC/getpathp.c Fri Apr 27 21:54:29 2007 @@ -650,7 +650,7 @@ start of the path in question - even if this is one character before the start of the buffer */ - while (*look != DELIM && look >= module_search_path) + while (look >= module_search_path && *look != DELIM) look--; nchars = lookEnd-look; strncpy(lookBuf, look+1, nchars); Modified: python/branches/p3yk/PCbuild/pythoncore.vcproj ============================================================================== --- python/branches/p3yk/PCbuild/pythoncore.vcproj (original) +++ python/branches/p3yk/PCbuild/pythoncore.vcproj Fri Apr 27 21:54:29 2007 @@ -461,7 +461,7 @@ RelativePath="..\Objects\codeobject.c"> + RelativePath="..\Modules\_collectionsmodule.c"> Modified: python/branches/p3yk/PCbuild8/pythoncore.vcproj ============================================================================== --- python/branches/p3yk/PCbuild8/pythoncore.vcproj (original) +++ python/branches/p3yk/PCbuild8/pythoncore.vcproj Fri Apr 27 21:54:29 2007 @@ -1381,7 +1381,7 @@ > cf_flags & PyCF_SOURCE_IS_UTF8) { c.c_encoding = "utf-8"; if (TYPE(n) == encoding_decl) { - ast_error(n, "encoding declaration in Unicode string"); - goto error; + ast_error(n, "encoding declaration in Unicode string"); + goto error; } } else if (TYPE(n) == encoding_decl) { c.c_encoding = STR(n); @@ -206,7 +207,7 @@ case file_input: stmts = asdl_seq_new(num_stmts(n), arena); if (!stmts) - return NULL; + return NULL; for (i = 0; i < NCH(n) - 1; i++) { ch = CHILD(n, i); if (TYPE(ch) == NEWLINE) @@ -346,8 +347,8 @@ switch (e->kind) { case Attribute_kind: if (ctx == Store && - !strcmp(PyString_AS_STRING(e->v.Attribute.attr), "None")) { - return ast_error(n, "assignment to None"); + !strcmp(PyString_AS_STRING(e->v.Attribute.attr), "None")) { + return ast_error(n, "assignment to None"); } e->v.Attribute.ctx = ctx; break; @@ -1075,34 +1076,34 @@ static int count_comp_fors(const node *n) { - int n_fors = 0; - node *ch = CHILD(n, 1); + int n_fors = 0; + node *ch = CHILD(n, 1); - count_comp_for: - n_fors++; - REQ(ch, comp_for); - if (NCH(ch) == 5) - ch = CHILD(ch, 4); - else - return n_fors; - count_comp_iter: - REQ(ch, comp_iter); - ch = CHILD(ch, 0); - if (TYPE(ch) == comp_for) - goto count_comp_for; - else if (TYPE(ch) == comp_if) { - if (NCH(ch) == 3) { - ch = CHILD(ch, 2); - goto count_comp_iter; - } - else - return n_fors; + count_comp_for: + n_fors++; + REQ(ch, comp_for); + if (NCH(ch) == 5) + ch = CHILD(ch, 4); + else + return n_fors; + count_comp_iter: + REQ(ch, comp_iter); + ch = CHILD(ch, 0); + if (TYPE(ch) == comp_for) + goto count_comp_for; + else if (TYPE(ch) == comp_if) { + if (NCH(ch) == 3) { + ch = CHILD(ch, 2); + goto count_comp_iter; } + else + return n_fors; + } - /* Should never be reached */ - PyErr_SetString(PyExc_SystemError, - "logic error in count_comp_fors"); - return -1; + /* Should never be reached */ + PyErr_SetString(PyExc_SystemError, + "logic error in count_comp_fors"); + return -1; } /* Count the number of 'if' statements in a comprehension. @@ -1113,19 +1114,19 @@ static int count_comp_ifs(const node *n) { - int n_ifs = 0; + int n_ifs = 0; - while (1) { - REQ(n, comp_iter); - if (TYPE(CHILD(n, 0)) == comp_for) - return n_ifs; - n = CHILD(n, 0); - REQ(n, comp_if); - n_ifs++; - if (NCH(n) == 2) - return n_ifs; - n = CHILD(n, 2); - } + while (1) { + REQ(n, comp_iter); + if (TYPE(CHILD(n, 0)) == comp_for) + return n_ifs; + n = CHILD(n, 0); + REQ(n, comp_if); + n_ifs++; + if (NCH(n) == 2) + return n_ifs; + n = CHILD(n, 2); + } } static expr_ty @@ -1451,53 +1452,53 @@ static expr_ty ast_for_binop(struct compiling *c, const node *n) { - /* Must account for a sequence of expressions. - How should A op B op C by represented? - BinOp(BinOp(A, op, B), op, C). - */ + /* Must account for a sequence of expressions. + How should A op B op C by represented? + BinOp(BinOp(A, op, B), op, C). + */ - int i, nops; - expr_ty expr1, expr2, result; - operator_ty newoperator; + int i, nops; + expr_ty expr1, expr2, result; + operator_ty newoperator; - expr1 = ast_for_expr(c, CHILD(n, 0)); - if (!expr1) - return NULL; + expr1 = ast_for_expr(c, CHILD(n, 0)); + if (!expr1) + return NULL; - expr2 = ast_for_expr(c, CHILD(n, 2)); - if (!expr2) - return NULL; + expr2 = ast_for_expr(c, CHILD(n, 2)); + if (!expr2) + return NULL; - newoperator = get_operator(CHILD(n, 1)); - if (!newoperator) - return NULL; + newoperator = get_operator(CHILD(n, 1)); + if (!newoperator) + return NULL; - result = BinOp(expr1, newoperator, expr2, LINENO(n), n->n_col_offset, - c->c_arena); - if (!result) - return NULL; + result = BinOp(expr1, newoperator, expr2, LINENO(n), n->n_col_offset, + c->c_arena); + if (!result) + return NULL; - nops = (NCH(n) - 1) / 2; - for (i = 1; i < nops; i++) { - expr_ty tmp_result, tmp; - const node* next_oper = CHILD(n, i * 2 + 1); + nops = (NCH(n) - 1) / 2; + for (i = 1; i < nops; i++) { + expr_ty tmp_result, tmp; + const node* next_oper = CHILD(n, i * 2 + 1); - newoperator = get_operator(next_oper); - if (!newoperator) - return NULL; + newoperator = get_operator(next_oper); + if (!newoperator) + return NULL; - tmp = ast_for_expr(c, CHILD(n, i * 2 + 2)); - if (!tmp) - return NULL; + tmp = ast_for_expr(c, CHILD(n, i * 2 + 2)); + if (!tmp) + return NULL; - tmp_result = BinOp(result, newoperator, tmp, - LINENO(next_oper), next_oper->n_col_offset, - c->c_arena); - if (!tmp) - return NULL; - result = tmp_result; - } - return result; + tmp_result = BinOp(result, newoperator, tmp, + LINENO(next_oper), next_oper->n_col_offset, + c->c_arena); + if (!tmp) + return NULL; + result = tmp_result; + } + return result; } static expr_ty @@ -2532,7 +2533,8 @@ if (!suite_seq) return NULL; - return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset, c->c_arena); + return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset, + c->c_arena); } s = STR(CHILD(n, 4)); @@ -2554,10 +2556,13 @@ if (!seq2) return NULL; - return If(expression, seq1, seq2, LINENO(n), n->n_col_offset, c->c_arena); + return If(expression, seq1, seq2, LINENO(n), n->n_col_offset, + c->c_arena); } else if (s[2] == 'i') { int i, n_elif, has_else = 0; + expr_ty expression; + asdl_seq *suite_seq; asdl_seq *orelse = NULL; n_elif = NCH(n) - 4; /* must reference the child n_elif+1 since 'else' token is third, @@ -2570,8 +2575,7 @@ n_elif /= 4; if (has_else) { - expr_ty expression; - asdl_seq *seq1, *seq2; + asdl_seq *suite_seq2; orelse = asdl_seq_new(1, c->c_arena); if (!orelse) @@ -2579,24 +2583,24 @@ expression = ast_for_expr(c, CHILD(n, NCH(n) - 6)); if (!expression) return NULL; - seq1 = ast_for_suite(c, CHILD(n, NCH(n) - 4)); - if (!seq1) + suite_seq = ast_for_suite(c, CHILD(n, NCH(n) - 4)); + if (!suite_seq) return NULL; - seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1)); - if (!seq2) + suite_seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1)); + if (!suite_seq2) return NULL; - asdl_seq_SET(orelse, 0, If(expression, seq1, seq2, - LINENO(CHILD(n, NCH(n) - 6)), CHILD(n, NCH(n) - 6)->n_col_offset, - c->c_arena)); + asdl_seq_SET(orelse, 0, + If(expression, suite_seq, suite_seq2, + LINENO(CHILD(n, NCH(n) - 6)), + CHILD(n, NCH(n) - 6)->n_col_offset, + c->c_arena)); /* the just-created orelse handled the last elif */ n_elif--; } for (i = 0; i < n_elif; i++) { int off = 5 + (n_elif - i - 1) * 4; - expr_ty expression; - asdl_seq *suite_seq; asdl_seq *newobj = asdl_seq_new(1, c->c_arena); if (!newobj) return NULL; @@ -2609,12 +2613,18 @@ asdl_seq_SET(newobj, 0, If(expression, suite_seq, orelse, - LINENO(CHILD(n, off)), CHILD(n, off)->n_col_offset, c->c_arena)); + LINENO(CHILD(n, off)), + CHILD(n, off)->n_col_offset, c->c_arena)); orelse = newobj; } - return If(ast_for_expr(c, CHILD(n, 1)), - ast_for_suite(c, CHILD(n, 3)), - orelse, LINENO(n), n->n_col_offset, c->c_arena); + expression = ast_for_expr(c, CHILD(n, 1)); + if (!expression) + return NULL; + suite_seq = ast_for_suite(c, CHILD(n, 3)); + if (!suite_seq) + return NULL; + return If(expression, suite_seq, orelse, + LINENO(n), n->n_col_offset, c->c_arena); } PyErr_Format(PyExc_SystemError, @@ -2988,137 +2998,137 @@ static PyObject * parsenumber(const char *s) { - const char *end; - long x; - double dx; + const char *end; + long x; + double dx; #ifndef WITHOUT_COMPLEX - Py_complex c; - int imflag; + Py_complex c; + int imflag; #endif - errno = 0; - end = s + strlen(s) - 1; + errno = 0; + end = s + strlen(s) - 1; #ifndef WITHOUT_COMPLEX - imflag = *end == 'j' || *end == 'J'; + imflag = *end == 'j' || *end == 'J'; #endif - if (*end == 'l' || *end == 'L') - return PyLong_FromString((char *)s, (char **)0, 0); - if (s[0] == '0') { - x = (long) PyOS_strtoul((char *)s, (char **)&end, 0); - if (x < 0 && errno == 0) { - return PyLong_FromString((char *)s, - (char **)0, - 0); - } + if (*end == 'l' || *end == 'L') + return PyLong_FromString((char *)s, (char **)0, 0); + if (s[0] == '0') { + x = (long) PyOS_strtoul((char *)s, (char **)&end, 0); + if (x < 0 && errno == 0) { + return PyLong_FromString((char *)s, + (char **)0, + 0); } - else - x = PyOS_strtol((char *)s, (char **)&end, 0); - if (*end == '\0') { - if (errno != 0) - return PyLong_FromString((char *)s, (char **)0, 0); - return PyInt_FromLong(x); - } - /* XXX Huge floats may silently fail */ + } + else + x = PyOS_strtol((char *)s, (char **)&end, 0); + if (*end == '\0') { + if (errno != 0) + return PyLong_FromString((char *)s, (char **)0, 0); + return PyInt_FromLong(x); + } + /* XXX Huge floats may silently fail */ #ifndef WITHOUT_COMPLEX - if (imflag) { - c.real = 0.; - PyFPE_START_PROTECT("atof", return 0) - c.imag = PyOS_ascii_atof(s); - PyFPE_END_PROTECT(c) - return PyComplex_FromCComplex(c); - } - else + if (imflag) { + c.real = 0.; + PyFPE_START_PROTECT("atof", return 0) + c.imag = PyOS_ascii_atof(s); + PyFPE_END_PROTECT(c) + return PyComplex_FromCComplex(c); + } + else #endif - { - PyFPE_START_PROTECT("atof", return 0) - dx = PyOS_ascii_atof(s); - PyFPE_END_PROTECT(dx) - return PyFloat_FromDouble(dx); - } + { + PyFPE_START_PROTECT("atof", return 0) + dx = PyOS_ascii_atof(s); + PyFPE_END_PROTECT(dx) + return PyFloat_FromDouble(dx); + } } static PyObject * decode_utf8(const char **sPtr, const char *end, char* encoding) { #ifndef Py_USING_UNICODE - Py_FatalError("decode_utf8 should not be called in this build."); - return NULL; + Py_FatalError("decode_utf8 should not be called in this build."); + return NULL; #else - PyObject *u, *v; - char *s, *t; - t = s = (char *)*sPtr; - /* while (s < end && *s != '\\') s++; */ /* inefficient for u".." */ - while (s < end && (*s & 0x80)) s++; - *sPtr = s; - u = PyUnicode_DecodeUTF8(t, s - t, NULL); - if (u == NULL) - return NULL; - v = PyUnicode_AsEncodedString(u, encoding, NULL); - Py_DECREF(u); - return v; + PyObject *u, *v; + char *s, *t; + t = s = (char *)*sPtr; + /* while (s < end && *s != '\\') s++; */ /* inefficient for u".." */ + while (s < end && (*s & 0x80)) s++; + *sPtr = s; + u = PyUnicode_DecodeUTF8(t, s - t, NULL); + if (u == NULL) + return NULL; + v = PyUnicode_AsEncodedString(u, encoding, NULL); + Py_DECREF(u); + return v; #endif } static PyObject * decode_unicode(const char *s, size_t len, int rawmode, const char *encoding) { - PyObject *v, *u; - char *buf; - char *p; - const char *end; - if (encoding == NULL) { - buf = (char *)s; - u = NULL; - } else if (strcmp(encoding, "iso-8859-1") == 0) { - buf = (char *)s; - u = NULL; - } else { - /* "\XX" may become "\u005c\uHHLL" (12 bytes) */ - u = PyString_FromStringAndSize((char *)NULL, len * 4); - if (u == NULL) - return NULL; - p = buf = PyString_AsString(u); - end = s + len; - while (s < end) { - if (*s == '\\') { - *p++ = *s++; - if (*s & 0x80) { - strcpy(p, "u005c"); - p += 5; - } - } - if (*s & 0x80) { /* XXX inefficient */ - PyObject *w; - char *r; - Py_ssize_t rn, i; - w = decode_utf8(&s, end, "utf-16-be"); - if (w == NULL) { - Py_DECREF(u); - return NULL; - } - r = PyString_AsString(w); - rn = PyString_Size(w); - assert(rn % 2 == 0); - for (i = 0; i < rn; i += 2) { - sprintf(p, "\\u%02x%02x", - r[i + 0] & 0xFF, - r[i + 1] & 0xFF); - p += 6; - } - Py_DECREF(w); - } else { - *p++ = *s++; - } - } - len = p - buf; - s = buf; + PyObject *v, *u; + char *buf; + char *p; + const char *end; + if (encoding == NULL) { + buf = (char *)s; + u = NULL; + } else if (strcmp(encoding, "iso-8859-1") == 0) { + buf = (char *)s; + u = NULL; + } else { + /* "\XX" may become "\u005c\uHHLL" (12 bytes) */ + u = PyString_FromStringAndSize((char *)NULL, len * 4); + if (u == NULL) + return NULL; + p = buf = PyString_AsString(u); + end = s + len; + while (s < end) { + if (*s == '\\') { + *p++ = *s++; + if (*s & 0x80) { + strcpy(p, "u005c"); + p += 5; + } + } + if (*s & 0x80) { /* XXX inefficient */ + PyObject *w; + char *r; + Py_ssize_t rn, i; + w = decode_utf8(&s, end, "utf-16-be"); + if (w == NULL) { + Py_DECREF(u); + return NULL; + } + r = PyString_AsString(w); + rn = PyString_Size(w); + assert(rn % 2 == 0); + for (i = 0; i < rn; i += 2) { + sprintf(p, "\\u%02x%02x", + r[i + 0] & 0xFF, + r[i + 1] & 0xFF); + p += 6; + } + Py_DECREF(w); + } else { + *p++ = *s++; + } } - if (rawmode) - v = PyUnicode_DecodeRawUnicodeEscape(s, len, NULL); - else - v = PyUnicode_DecodeUnicodeEscape(s, len, NULL); - Py_XDECREF(u); - return v; + len = p - buf; + s = buf; + } + if (rawmode) + v = PyUnicode_DecodeRawUnicodeEscape(s, len, NULL); + else + v = PyUnicode_DecodeUnicodeEscape(s, len, NULL); + Py_XDECREF(u); + return v; } /* s is a Python string literal, including the bracketing quote characters, @@ -3128,95 +3138,95 @@ static PyObject * parsestr(const node *n, const char *encoding, int *bytesmode) { - size_t len; - const char *s = STR(n); - int quote = Py_CHARMASK(*s); - int rawmode = 0; - int need_encoding; - int unicode = 0; + size_t len; + const char *s = STR(n); + int quote = Py_CHARMASK(*s); + int rawmode = 0; + int need_encoding; + int unicode = 0; - if (isalpha(quote) || quote == '_') { - if (quote == 'u' || quote == 'U') { - quote = *++s; - unicode = 1; - } - if (quote == 'b' || quote == 'B') { - quote = *++s; - *bytesmode = 1; - } - if (quote == 'r' || quote == 'R') { - quote = *++s; - rawmode = 1; - } + if (isalpha(quote) || quote == '_') { + if (quote == 'u' || quote == 'U') { + quote = *++s; + unicode = 1; } - if (quote != '\'' && quote != '\"') { - PyErr_BadInternalCall(); - return NULL; + if (quote == 'b' || quote == 'B') { + quote = *++s; + *bytesmode = 1; + } + if (quote == 'r' || quote == 'R') { + quote = *++s; + rawmode = 1; } - if (unicode && *bytesmode) { - ast_error(n, "string cannot be both bytes and unicode"); - return NULL; - } - s++; - len = strlen(s); - if (len > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "string to parse is too long"); - return NULL; - } - if (s[--len] != quote) { - PyErr_BadInternalCall(); - return NULL; - } - if (len >= 4 && s[0] == quote && s[1] == quote) { - s += 2; - len -= 2; - if (s[--len] != quote || s[--len] != quote) { - PyErr_BadInternalCall(); - return NULL; - } + } + if (quote != '\'' && quote != '\"') { + PyErr_BadInternalCall(); + return NULL; + } + if (unicode && *bytesmode) { + ast_error(n, "string cannot be both bytes and unicode"); + return NULL; + } + s++; + len = strlen(s); + if (len > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "string to parse is too long"); + return NULL; + } + if (s[--len] != quote) { + PyErr_BadInternalCall(); + return NULL; + } + if (len >= 4 && s[0] == quote && s[1] == quote) { + s += 2; + len -= 2; + if (s[--len] != quote || s[--len] != quote) { + PyErr_BadInternalCall(); + return NULL; } + } #ifdef Py_USING_UNICODE - if (unicode || Py_UnicodeFlag) { - return decode_unicode(s, len, rawmode, encoding); - } + if (unicode || Py_UnicodeFlag) { + return decode_unicode(s, len, rawmode, encoding); + } #endif - if (*bytesmode) { - /* Disallow non-ascii characters (but not escapes) */ - const char *c; - for (c = s; *c; c++) { - if (Py_CHARMASK(*c) >= 0x80) { - ast_error(n, "bytes can only contain ASCII " - "literal characters."); - return NULL; - } - } - } - need_encoding = (!*bytesmode && encoding != NULL && - strcmp(encoding, "utf-8") != 0 && - strcmp(encoding, "iso-8859-1") != 0); - if (rawmode || strchr(s, '\\') == NULL) { - if (need_encoding) { + if (*bytesmode) { + /* Disallow non-ascii characters (but not escapes) */ + const char *c; + for (c = s; *c; c++) { + if (Py_CHARMASK(*c) >= 0x80) { + ast_error(n, "bytes can only contain ASCII " + "literal characters."); + return NULL; + } + } + } + need_encoding = (!*bytesmode && encoding != NULL && + strcmp(encoding, "utf-8") != 0 && + strcmp(encoding, "iso-8859-1") != 0); + if (rawmode || strchr(s, '\\') == NULL) { + if (need_encoding) { #ifndef Py_USING_UNICODE - /* This should not happen - we never see any other - encoding. */ - Py_FatalError( - "cannot deal with encodings in this build."); + /* This should not happen - we never see any other + encoding. */ + Py_FatalError( + "cannot deal with encodings in this build."); #else - PyObject *v, *u = PyUnicode_DecodeUTF8(s, len, NULL); - if (u == NULL) - return NULL; - v = PyUnicode_AsEncodedString(u, encoding, NULL); - Py_DECREF(u); - return v; + PyObject *v, *u = PyUnicode_DecodeUTF8(s, len, NULL); + if (u == NULL) + return NULL; + v = PyUnicode_AsEncodedString(u, encoding, NULL); + Py_DECREF(u); + return v; #endif - } else { - return PyString_FromStringAndSize(s, len); - } + } else { + return PyString_FromStringAndSize(s, len); } + } - return PyString_DecodeEscape(s, len, NULL, unicode, - need_encoding ? encoding : NULL); + return PyString_DecodeEscape(s, len, NULL, unicode, + need_encoding ? encoding : NULL); } /* Build a Python string object out of a STRING atom. This takes care of @@ -3226,43 +3236,43 @@ static PyObject * parsestrplus(struct compiling *c, const node *n, int *bytesmode) { - PyObject *v; - int i; - REQ(CHILD(n, 0), STRING); - v = parsestr(CHILD(n, 0), c->c_encoding, bytesmode); - if (v != NULL) { - /* String literal concatenation */ - for (i = 1; i < NCH(n); i++) { - PyObject *s; - int subbm = 0; - s = parsestr(CHILD(n, i), c->c_encoding, &subbm); - if (s == NULL) - goto onError; - if (*bytesmode != subbm) { - ast_error(n, "cannot mix bytes and nonbytes" - "literals"); - goto onError; - } - if (PyString_Check(v) && PyString_Check(s)) { - PyString_ConcatAndDel(&v, s); - if (v == NULL) - goto onError; - } + PyObject *v; + int i; + REQ(CHILD(n, 0), STRING); + v = parsestr(CHILD(n, 0), c->c_encoding, bytesmode); + if (v != NULL) { + /* String literal concatenation */ + for (i = 1; i < NCH(n); i++) { + PyObject *s; + int subbm = 0; + s = parsestr(CHILD(n, i), c->c_encoding, &subbm); + if (s == NULL) + goto onError; + if (*bytesmode != subbm) { + ast_error(n, "cannot mix bytes and nonbytes" + "literals"); + goto onError; + } + if (PyString_Check(v) && PyString_Check(s)) { + PyString_ConcatAndDel(&v, s); + if (v == NULL) + goto onError; + } #ifdef Py_USING_UNICODE - else { - PyObject *temp = PyUnicode_Concat(v, s); - Py_DECREF(s); - Py_DECREF(v); - v = temp; - if (v == NULL) - goto onError; - } + else { + PyObject *temp = PyUnicode_Concat(v, s); + Py_DECREF(s); + Py_DECREF(v); + v = temp; + if (v == NULL) + goto onError; + } #endif - } } - return v; + } + return v; - onError: - Py_XDECREF(v); - return NULL; + onError: + Py_XDECREF(v); + return NULL; } Modified: python/branches/p3yk/Python/bltinmodule.c ============================================================================== --- python/branches/p3yk/Python/bltinmodule.c (original) +++ python/branches/p3yk/Python/bltinmodule.c Fri Apr 27 21:54:29 2007 @@ -441,7 +441,7 @@ Return negative if xy."); static PyObject * -builtin_compile(PyObject *self, PyObject *args) +builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) { char *str; char *filename; @@ -452,9 +452,12 @@ PyCompilerFlags cf; PyObject *result = NULL, *cmd, *tmp = NULL; Py_ssize_t length; + static char *kwlist[] = {"source", "filename", "mode", "flags", + "dont_inherit", NULL}; - if (!PyArg_ParseTuple(args, "Oss|ii:compile", &cmd, &filename, - &startstr, &supplied_flags, &dont_inherit)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oss|ii:compile", + kwlist, &cmd, &filename, &startstr, + &supplied_flags, &dont_inherit)) return NULL; cf.cf_flags = supplied_flags; @@ -542,7 +545,7 @@ " 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" +" for any other object: its attributes, its class's attributes, and\n" " recursively the attributes of its class's base classes."); static PyObject * @@ -2269,7 +2272,7 @@ {"callable", builtin_callable, METH_O, callable_doc}, {"chr", builtin_chr, METH_VARARGS, chr_doc}, {"cmp", builtin_cmp, METH_VARARGS, cmp_doc}, - {"compile", builtin_compile, METH_VARARGS, compile_doc}, + {"compile", (PyCFunction)builtin_compile, METH_VARARGS | METH_KEYWORDS, compile_doc}, {"delattr", builtin_delattr, METH_VARARGS, delattr_doc}, {"dir", builtin_dir, METH_VARARGS, dir_doc}, {"divmod", builtin_divmod, METH_VARARGS, divmod_doc}, Modified: python/branches/p3yk/Python/ceval.c ============================================================================== --- python/branches/p3yk/Python/ceval.c (original) +++ python/branches/p3yk/Python/ceval.c Fri Apr 27 21:54:29 2007 @@ -657,7 +657,7 @@ #define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \ lltrace && prtrace(TOP(), "stackadj")); \ assert(STACK_LEVEL() <= co->co_stacksize); } -#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER)) +#define EXT_POP(STACK_POINTER) (lltrace && prtrace((STACK_POINTER)[-1], "ext_pop"), *--(STACK_POINTER)) #else #define PUSH(v) BASIC_PUSH(v) #define POP() BASIC_POP() @@ -1657,12 +1657,10 @@ PUSH(w); } } else if (unpack_iterable(v, oparg, - stack_pointer + oparg)) + stack_pointer + oparg)) { stack_pointer += oparg; - else { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_SetString(PyExc_TypeError, - "unpack non-sequence"); + } else { + /* unpack_iterable() raised an exception */ why = WHY_EXCEPTION; } Py_DECREF(v); @@ -3877,7 +3875,7 @@ PyTypeObject *tp = u->ob_type; PySequenceMethods *sq = tp->tp_as_sequence; - if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) { + if (sq && sq->sq_ass_slice && ISINDEX(v) && ISINDEX(w)) { Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX; if (!_PyEval_SliceIndex(v, &ilow)) return -1; Modified: python/branches/p3yk/Python/compile.c ============================================================================== --- python/branches/p3yk/Python/compile.c (original) +++ python/branches/p3yk/Python/compile.c Fri Apr 27 21:54:29 2007 @@ -8,7 +8,7 @@ * 2. Builds a symbol table. See symtable.c. * 3. Generate code for basic blocks. See compiler_mod() in this file. * 4. Assemble the basic blocks into final code. See assemble() in - * this file. + * this file. * 5. Optimize the byte code (peephole optimizations). See peephole.c * * Note that compiler_mod() suggests module, but the module ast type @@ -204,7 +204,17 @@ } p = PyString_AsString(privateobj); nlen = strlen(name); - if (name[nlen-1] == '_' && name[nlen-2] == '_') { + /* Don't mangle __id__ or names with dots. + + The only time a name with a dot can occur is when + we are compiling an import statement that has a + package name. + + TODO(jhylton): Decide whether we want to support + mangling of the module name, e.g. __M.X. + */ + if ((name[nlen-1] == '_' && name[nlen-2] == '_') + || strchr(name, '.')) { Py_INCREF(ident); return ident; /* Don't mangle __whatever__ */ } @@ -439,7 +449,7 @@ struct compiler_unit *u; u = (struct compiler_unit *)PyObject_Malloc(sizeof( - struct compiler_unit)); + struct compiler_unit)); if (!u) { PyErr_NoMemory(); return 0; @@ -608,7 +618,7 @@ assert(b != NULL); if (b->b_instr == NULL) { b->b_instr = (struct instr *)PyObject_Malloc( - sizeof(struct instr) * DEFAULT_BLOCK_SIZE); + sizeof(struct instr) * DEFAULT_BLOCK_SIZE); if (b->b_instr == NULL) { PyErr_NoMemory(); return -1; @@ -628,7 +638,7 @@ } b->b_ialloc <<= 1; tmp = (struct instr *)PyObject_Realloc( - (void *)b->b_instr, newsize); + (void *)b->b_instr, newsize); if (tmp == NULL) { PyErr_NoMemory(); return -1; @@ -1148,7 +1158,7 @@ case Interactive_kind: c->c_interactive = 1; VISIT_SEQ_IN_SCOPE(c, stmt, - mod->v.Interactive.body); + mod->v.Interactive.body); break; case Expression_kind: VISIT_IN_SCOPE(c, expr, mod->v.Expression.body); @@ -1729,7 +1739,7 @@ compiler_use_next_block(c, next); ADDOP(c, POP_TOP); if (s->v.If.orelse) - VISIT_SEQ(c, stmt, s->v.If.orelse); + VISIT_SEQ(c, stmt, s->v.If.orelse); } compiler_use_next_block(c, end); return 1; @@ -1977,8 +1987,8 @@ s->v.TryExcept.handlers, i); if (!handler->type && i < n-1) return compiler_error(c, "default 'except:' must be last"); - c->u->u_lineno_set = 0; - c->u->u_lineno = handler->lineno; + c->u->u_lineno_set = 0; + c->u->u_lineno = handler->lineno; except = compiler_new_block(c); if (except == NULL) return 0; @@ -2321,7 +2331,7 @@ case Pass_kind: break; case Break_kind: - if (!compiler_in_loop(c)) + if (!compiler_in_loop(c)) return compiler_error(c, "'break' outside loop"); ADDOP(c, BREAK_LOOP); break; @@ -2459,7 +2469,7 @@ return compiler_error(c, "can not assign to __debug__"); } - mangled = _Py_Mangle(c->u->u_private, name); +mangled = _Py_Mangle(c->u->u_private, name); if (!mangled) return 0; @@ -2645,20 +2655,20 @@ if (cleanup == NULL) return 0; VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0)); + (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0)); } for (i = 1; i < n; i++) { ADDOP(c, DUP_TOP); ADDOP(c, ROT_THREE); ADDOP_I(c, COMPARE_OP, cmpop((cmpop_ty)(asdl_seq_GET( - e->v.Compare.ops, i - 1)))); + e->v.Compare.ops, i - 1)))); ADDOP_JREL(c, JUMP_IF_FALSE, cleanup); NEXT_BLOCK(c); ADDOP(c, POP_TOP); if (i < (n - 1)) VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); + (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); } VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n - 1)); ADDOP_I(c, COMPARE_OP, @@ -2968,7 +2978,7 @@ /* __debug__ is not assignable, so we can optimize * it away in if and while statements */ if (strcmp(PyString_AS_STRING(e->v.Name.id), - "__debug__") == 0) + "__debug__") == 0) return ! Py_OptimizeFlag; /* fall through */ default: @@ -3115,8 +3125,8 @@ int i, n; /* If expr e has a different line number than the last expr/stmt, - set a new line number for the next instruction. - */ + set a new line number for the next instruction. + */ if (e->lineno > c->u->u_lineno) { c->u->u_lineno = e->lineno; c->u->u_lineno_set = 0; @@ -3146,10 +3156,10 @@ for (i = 0; i < n; i++) { ADDOP(c, DUP_TOP); VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); + (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); ADDOP(c, ROT_TWO); VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); + (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); ADDOP(c, STORE_SUBSCR); } break; @@ -3331,13 +3341,13 @@ static int compiler_in_loop(struct compiler *c) { - int i; - struct compiler_unit *u = c->u; - for (i = 0; i < u->u_nfblocks; ++i) { - if (u->u_fblock[i].fb_type == LOOP) - return 1; - } - return 0; + int i; + struct compiler_unit *u = c->u; + for (i = 0; i < u->u_nfblocks; ++i) { + if (u->u_fblock[i].fb_type == LOOP) + return 1; + } + return 0; } /* Raises a SyntaxError and returns 0. If something goes wrong, a different exception may be raised. @@ -3523,7 +3533,7 @@ int i, n = asdl_seq_LEN(s->v.ExtSlice.dims); for (i = 0; i < n; i++) { slice_ty sub = (slice_ty)asdl_seq_GET( - s->v.ExtSlice.dims, i); + s->v.ExtSlice.dims, i); if (!compiler_visit_nested_slice(c, sub, ctx)) return 0; } @@ -3720,7 +3730,7 @@ increment is < 256. So, in the example above, assemble_lnotab (it used to be called com_set_lineno) should not (as was actually done until 2.2) expand 300, 300 to 255, 255, 45, 45, - but to 255, 0, 45, 255, 0, 45. + but to 255, 0, 45, 255, 0, 45. */ static int Modified: python/branches/p3yk/Python/dynload_win.c ============================================================================== --- python/branches/p3yk/Python/dynload_win.c (original) +++ python/branches/p3yk/Python/dynload_win.c Fri Apr 27 21:54:29 2007 @@ -13,16 +13,8 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef _DEBUG {"_d.pyd", "rb", C_EXTENSION}, - /* Temporarily disable .dll, to avoid conflicts between sqlite3.dll - and the sqlite3 package. If this needs to be reverted for 2.5, - some other solution for the naming conflict must be found. - {"_d.dll", "rb", C_EXTENSION}, - */ #else {".pyd", "rb", C_EXTENSION}, - /* Likewise - {".dll", "rb", C_EXTENSION}, - */ #endif {0, 0} }; Modified: python/branches/p3yk/Python/errors.c ============================================================================== --- python/branches/p3yk/Python/errors.c (original) +++ python/branches/p3yk/Python/errors.c Fri Apr 27 21:54:29 2007 @@ -599,8 +599,9 @@ PyFile_WriteString("Exception ", f); if (t) { PyObject* moduleName; - char* className = PyExceptionClass_Name(t); - + char* className; + assert(PyExceptionClass_Check(t)); + className = PyExceptionClass_Name(t); if (className != NULL) { char *dot = strrchr(className, '.'); if (dot != NULL) @@ -825,4 +826,3 @@ #ifdef __cplusplus } #endif - Deleted: /python/branches/p3yk/Python/fmod.c ============================================================================== --- /python/branches/p3yk/Python/fmod.c Fri Apr 27 21:54:29 2007 +++ (empty file) @@ -1,27 +0,0 @@ - -/* Portable fmod(x, y) implementation for systems that don't have it */ - -#include "pyconfig.h" - -#include "pyport.h" -#include - -double -fmod(double x, double y) -{ - double i, f; - - if (y == 0.0) { - errno = EDOM; - return 0.0; - } - - /* return f such that x = i*y + f for some integer i - such that |f| < |y| and f has the same sign as x */ - - i = floor(x/y); - f = x - i*y; - if ((x < 0.0) != (y < 0.0)) - f = f-y; - return f; -} Modified: python/branches/p3yk/Python/import.c ============================================================================== --- python/branches/p3yk/Python/import.c (original) +++ python/branches/p3yk/Python/import.c Fri Apr 27 21:54:29 2007 @@ -4,6 +4,7 @@ #include "Python.h" #include "Python-ast.h" +#undef Yield /* undefine macro conflicting with winbase.h */ #include "pyarena.h" #include "pythonrun.h" #include "errcode.h" @@ -347,6 +348,14 @@ return Py_None; } +static void +imp_modules_reloading_clear(void) +{ + PyInterpreterState *interp = PyThreadState_Get()->interp; + if (interp->modules_reloading != NULL) + PyDict_Clear(interp->modules_reloading); +} + /* Helper for sys */ PyObject * @@ -506,6 +515,7 @@ PyDict_Clear(modules); interp->modules = NULL; Py_DECREF(modules); + Py_CLEAR(interp->modules_reloading); } @@ -2408,13 +2418,21 @@ PyObject * PyImport_ReloadModule(PyObject *m) { + PyInterpreterState *interp = PyThreadState_Get()->interp; + PyObject *modules_reloading = interp->modules_reloading; PyObject *modules = PyImport_GetModuleDict(); - PyObject *path = NULL, *loader = NULL; + PyObject *path = NULL, *loader = NULL, *existing_m = NULL; char *name, *subname; char buf[MAXPATHLEN+1]; struct filedescr *fdp; FILE *fp = NULL; PyObject *newm; + + if (modules_reloading == NULL) { + Py_FatalError("PyImport_ReloadModule: " + "no modules_reloading dictionary!"); + return NULL; + } if (m == NULL || !PyModule_Check(m)) { PyErr_SetString(PyExc_TypeError, @@ -2430,20 +2448,33 @@ name); return NULL; } + existing_m = PyDict_GetItemString(modules_reloading, name); + if (existing_m != NULL) { + /* Due to a recursive reload, this module is already + being reloaded. */ + Py_INCREF(existing_m); + return existing_m; + } + if (PyDict_SetItemString(modules_reloading, name, m) < 0) + return NULL; + subname = strrchr(name, '.'); if (subname == NULL) subname = name; else { PyObject *parentname, *parent; parentname = PyString_FromStringAndSize(name, (subname-name)); - if (parentname == NULL) + if (parentname == NULL) { + imp_modules_reloading_clear(); return NULL; + } parent = PyDict_GetItem(modules, parentname); if (parent == NULL) { PyErr_Format(PyExc_ImportError, "reload(): parent %.200s not in sys.modules", PyString_AS_STRING(parentname)); Py_DECREF(parentname); + imp_modules_reloading_clear(); return NULL; } Py_DECREF(parentname); @@ -2458,6 +2489,7 @@ if (fdp == NULL) { Py_XDECREF(loader); + imp_modules_reloading_clear(); return NULL; } @@ -2474,6 +2506,7 @@ */ PyDict_SetItemString(modules, name, m); } + imp_modules_reloading_clear(); return newm; } @@ -2543,7 +2576,7 @@ if (import == NULL) goto err; - /* Call the _import__ function with the proper argument list */ + /* Call the __import__ function with the proper argument list */ r = PyObject_CallFunctionObjArgs(import, module_name, globals, globals, silly_list, NULL); Modified: python/branches/p3yk/Python/peephole.c ============================================================================== --- python/branches/p3yk/Python/peephole.c (original) +++ python/branches/p3yk/Python/peephole.c Fri Apr 27 21:54:29 2007 @@ -1,4 +1,4 @@ -/* Peehole optimizations for bytecode compiler. */ +/* Peephole optimizations for bytecode compiler. */ #include "Python.h" @@ -380,13 +380,17 @@ if (name == NULL || strcmp(name, "None") != 0) continue; for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) { - if (PyList_GET_ITEM(consts, j) == Py_None) { - codestr[i] = LOAD_CONST; - SETARG(codestr, i, j); - cumlc = lastlc + 1; + if (PyList_GET_ITEM(consts, j) == Py_None) break; - } } + if (j == PyList_GET_SIZE(consts)) { + if (PyList_Append(consts, Py_None) == -1) + goto exitUnchanged; + } + assert(PyList_GET_ITEM(consts, j) == Py_None); + codestr[i] = LOAD_CONST; + SETARG(codestr, i, j); + cumlc = lastlc + 1; break; /* Skip over LOAD_CONST trueconst Modified: python/branches/p3yk/Python/pystate.c ============================================================================== --- python/branches/p3yk/Python/pystate.c (original) +++ python/branches/p3yk/Python/pystate.c Fri Apr 27 21:54:29 2007 @@ -68,6 +68,7 @@ Py_FatalError("Can't initialize threads for interpreter"); #endif interp->modules = NULL; + interp->modules_reloading = NULL; interp->sysdict = NULL; interp->builtins = NULL; interp->tstate_head = NULL; @@ -107,6 +108,7 @@ Py_CLEAR(interp->codec_search_cache); Py_CLEAR(interp->codec_error_registry); Py_CLEAR(interp->modules); + Py_CLEAR(interp->modules_reloading); Py_CLEAR(interp->sysdict); Py_CLEAR(interp->builtins); } Modified: python/branches/p3yk/Python/pythonrun.c ============================================================================== --- python/branches/p3yk/Python/pythonrun.c (original) +++ python/branches/p3yk/Python/pythonrun.c Fri Apr 27 21:54:29 2007 @@ -4,6 +4,7 @@ #include "Python.h" #include "Python-ast.h" +#undef Yield /* undefine macro conflicting with winbase.h */ #include "grammar.h" #include "node.h" #include "token.h" @@ -71,6 +72,7 @@ int Py_DebugFlag; /* Needed by parser.c */ int Py_VerboseFlag; /* Needed by import.c */ int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ +int Py_InspectFlag; /* Needed to determine whether to exit at SystemError */ int Py_NoSiteFlag; /* Suppress 'import site' */ int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */ int Py_FrozenFlag; /* Needed by getpath.c */ @@ -194,6 +196,9 @@ interp->modules = PyDict_New(); if (interp->modules == NULL) Py_FatalError("Py_Initialize: can't make modules dictionary"); + interp->modules_reloading = PyDict_New(); + if (interp->modules_reloading == NULL) + Py_FatalError("Py_Initialize: can't make modules_reloading dictionary"); #ifdef Py_USING_UNICODE /* Init Unicode implementation; relies on the codec registry */ @@ -531,6 +536,7 @@ /* XXX The following is lax in error checking */ interp->modules = PyDict_New(); + interp->modules_reloading = PyDict_New(); bimod = _PyImport_FindExtension("__builtin__", "__builtin__"); if (bimod != NULL) { @@ -847,6 +853,7 @@ { PyObject *m, *d, *v; const char *ext; + int set_file_name = 0, ret; m = PyImport_AddModule("__main__"); if (m == NULL) @@ -860,6 +867,7 @@ Py_DECREF(f); return -1; } + set_file_name = 1; Py_DECREF(f); } ext = filename + strlen(filename) - 4; @@ -869,7 +877,8 @@ fclose(fp); if ((fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "python: Can't reopen .pyc file\n"); - return -1; + ret = -1; + goto done; } /* Turn on optimization if a .pyo file is given */ if (strcmp(ext, ".pyo") == 0) @@ -881,10 +890,15 @@ } if (v == NULL) { PyErr_Print(); - return -1; + ret = -1; + goto done; } Py_DECREF(v); - return 0; + ret = 0; + done: + if (set_file_name && PyDict_DelItemString(d, "__file__")) + PyErr_Clear(); + return ret; } int @@ -1014,6 +1028,11 @@ PyObject *exception, *value, *tb; int exitcode = 0; + if (Py_InspectFlag) + /* Don't exit if -i flag was given. This flag is set to 0 + * when entering interactive mode for inspecting. */ + return; + PyErr_Fetch(&exception, &value, &tb); fflush(stdout); if (value == NULL || value == Py_None) @@ -1201,8 +1220,8 @@ err = PyFile_WriteObject(s, f, Py_PRINT_RAW); Py_XDECREF(s); } - if (err == 0) - err = PyFile_WriteString("\n", f); + /* try to write a newline in any case */ + err += PyFile_WriteString("\n", f); } Py_DECREF(value); /* If an error happened here, don't show it. @@ -1240,12 +1259,12 @@ mod = PyParser_ASTFromFile(fp, filename, start, 0, 0, flags, NULL, arena); + if (closeit) + fclose(fp); if (mod == NULL) { PyArena_Free(arena); return NULL; } - if (closeit) - fclose(fp); ret = run_mod(mod, filename, globals, locals, flags, arena); PyArena_Free(arena); return ret; Modified: python/branches/p3yk/Python/sysmodule.c ============================================================================== --- python/branches/p3yk/Python/sysmodule.c (original) +++ python/branches/p3yk/Python/sysmodule.c Fri Apr 27 21:54:29 2007 @@ -1014,8 +1014,6 @@ } else if (istag || strncmp(br_start, "branches", 8) == 0) { len = br_end2 - br_start; - assert(len >= 13); - assert(len < (sizeof(patchlevel_revision) - 13)); strncpy(branch, br_start, len); branch[len] = '\0'; @@ -1034,6 +1032,8 @@ svn_revision = svnversion; else if (istag) { len = strlen(_patchlevel_revision); + assert(len >= 13); + assert(len < (sizeof(patchlevel_revision) + 13)); strncpy(patchlevel_revision, _patchlevel_revision + 11, len - 13); patchlevel_revision[len - 13] = '\0'; Modified: python/branches/p3yk/Python/thread_nt.h ============================================================================== --- python/branches/p3yk/Python/thread_nt.h (original) +++ python/branches/p3yk/Python/thread_nt.h Fri Apr 27 21:54:29 2007 @@ -202,12 +202,12 @@ * too many threads". */ dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n", - PyThread_get_thread_ident(), rv, errno)); + PyThread_get_thread_ident(), (void*)rv, errno)); obj.id = -1; } else { dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", - PyThread_get_thread_ident(), rv)); + PyThread_get_thread_ident(), (void*)rv)); /* wait for thread to initialize, so we can get its id */ WaitForSingleObject(obj.done, INFINITE); assert(obj.id != -1); @@ -333,7 +333,7 @@ dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); + dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError())); } /* minimum/maximum thread stack sizes supported */ Modified: python/branches/p3yk/README ============================================================================== --- python/branches/p3yk/README (original) +++ python/branches/p3yk/README Fri Apr 27 21:54:29 2007 @@ -578,9 +578,9 @@ MacOSX: The tests will crash on both 10.1 and 10.2 with SEGV in test_re and test_sre due to the small default stack size. If you set the stack size to 2048 before doing a "make test" the - failure can be avoided. If you're using the tcsh (the default - on OSX), or csh shells use "limit stacksize 2048" and for the - bash shell, use "ulimit -s 2048". + failure can be avoided. If you're using the tcsh or csh shells, + use "limit stacksize 2048" and for the bash shell (the default + as of OSX 10.3), use "ulimit -s 2048". On naked Darwin you may want to add the configure option "--disable-toolbox-glue" to disable the glue code for the Carbon Modified: python/branches/p3yk/Tools/pybench/pybench.py ============================================================================== --- python/branches/p3yk/Tools/pybench/pybench.py (original) +++ python/branches/p3yk/Tools/pybench/pybench.py Fri Apr 27 21:54:29 2007 @@ -167,7 +167,7 @@ call of .run(). If you change a test in some way, don't forget to increase - it's version number. + its version number. """ Modified: python/branches/p3yk/configure.in ============================================================================== --- python/branches/p3yk/configure.in (original) +++ python/branches/p3yk/configure.in Fri Apr 27 21:54:29 2007 @@ -1571,9 +1571,11 @@ then case $ac_sys_system/$ac_sys_release in SunOS*) if test "$GCC" = yes; - then CCSHARED="-fPIC"; - else CCSHARED="-xcode=pic32"; - fi;; + then CCSHARED="-fPIC"; + elif test `uname -p` = sparc; + then CCSHARED="-xcode=pic32"; + else CCSHARED="-Kpic"; + fi;; hp*|HP*) if test "$GCC" = yes; then CCSHARED="-fPIC"; else CCSHARED="+z"; Modified: python/branches/p3yk/setup.py ============================================================================== --- python/branches/p3yk/setup.py (original) +++ python/branches/p3yk/setup.py Fri Apr 27 21:54:29 2007 @@ -91,10 +91,14 @@ class PyBuildExt(build_ext): + def __init__(self, dist): + build_ext.__init__(self, dist) + self.failed = [] + def build_extensions(self): # Detect which modules should be compiled - self.detect_modules() + missing = self.detect_modules() # Remove modules that are present on the disabled list self.extensions = [ext for ext in self.extensions @@ -178,6 +182,31 @@ build_ext.build_extensions(self) + longest = max([len(e.name) for e in self.extensions]) + if self.failed: + longest = max(longest, max([len(name) for name in self.failed])) + + def print_three_column(lst): + lst.sort(key=str.lower) + # guarantee zip() doesn't drop anything + while len(lst) % 3: + lst.append("") + for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]): + print("%-*s %-*s %-*s" % (longest, e, longest, f, + longest, g)) + print() + + if missing: + print() + print("Failed to find the necessary bits to build these modules:") + print_three_column(missing) + + if self.failed: + failed = self.failed[:] + print() + print("Failed to build these modules:") + print_three_column(failed) + def build_extension(self, ext): if ext.name == '_ctypes': @@ -189,6 +218,7 @@ except (CCompilerError, DistutilsError) as why: self.announce('WARNING: building of extension "%s" failed: %s' % (ext.name, sys.exc_info()[1])) + self.failed.append(ext.name) return # Workaround for Mac OS X: The Carbon-based modules cannot be # reliably imported into a command-line Python @@ -209,6 +239,7 @@ try: imp.load_dynamic(ext.name, ext_filename) except ImportError as why: + self.failed.append(ext.name) self.announce('*** WARNING: renaming "%s" since importing it' ' failed: %s' % (ext.name, why), level=3) assert not self.inplace @@ -234,6 +265,7 @@ self.announce('*** WARNING: importing extension "%s" ' 'failed with %s: %s' % (ext.name, exc_type, why), level=3) + self.failed.append(ext.name) def get_platform(self): # Get value of sys.platform @@ -299,6 +331,7 @@ ] inc_dirs = self.compiler.include_dirs + ['/usr/include'] exts = [] + missing = [] config_h = sysconfig.get_config_h_filename() config_h_vars = sysconfig.parse_config_h(open(config_h)) @@ -370,7 +403,7 @@ # fast iterator tools implemented in C exts.append( Extension("itertools", ["itertoolsmodule.c"]) ) # high-performance collections - exts.append( Extension("collections", ["collectionsmodule.c"]) ) + exts.append( Extension("_collections", ["_collectionsmodule.c"]) ) # bisect exts.append( Extension("_bisect", ["_bisectmodule.c"]) ) # heapq @@ -389,6 +422,8 @@ # static Unicode character database if have_unicode: exts.append( Extension('unicodedata', ['unicodedata.c']) ) + else: + missing.append('unicodedata') # access to ISO C locale support data = open('pyconfig.h').read() m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data) @@ -421,6 +456,11 @@ if (config_h_vars.get('HAVE_GETSPNAM', False) or config_h_vars.get('HAVE_GETSPENT', False)): exts.append( Extension('spwd', ['spwdmodule.c']) ) + else: + missing.append('spwd') + else: + missing.extend(['pwd', 'grp', 'spwd']) + # select(2); not on ancient System V exts.append( Extension('select', ['selectmodule.c']) ) @@ -437,11 +477,15 @@ # Memory-mapped files (also works on Win32). if platform not in ['atheos', 'mac']: exts.append( Extension('mmap', ['mmapmodule.c']) ) + else: + missing.append('mmap') # Lance Ellinghaus's syslog module if platform not in ['mac']: # syslog daemon interface exts.append( Extension('syslog', ['syslogmodule.c']) ) + else: + missing.append('syslog') # George Neville-Neil's timing module: # Deprecated in PEP 4 http://www.python.org/peps/pep-0004.html @@ -468,6 +512,8 @@ exts.append( Extension('imageop', ['imageop.c']) ) # Read SGI RGB image files (but coded portably) exts.append( Extension('rgbimg', ['rgbimgmodule.c']) ) + else: + missing.extend(['imageop', 'rgbimg']) # readline do_readline = self.compiler.find_library_file(lib_dirs, 'readline') @@ -505,6 +551,9 @@ library_dirs=['/usr/lib/termcap'], extra_link_args=readline_extra_link_args, libraries=readline_libs) ) + else: + missing.append('readline') + if platform not in ['mac']: # crypt module. @@ -513,6 +562,8 @@ else: libs = [] exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) ) + else: + missing.append('crypt') # CSV files exts.append( Extension('_csv', ['_csv.c']) ) @@ -545,6 +596,8 @@ library_dirs = ssl_libs, libraries = ['ssl', 'crypto'], depends = ['socketmodule.h']), ) + else: + missing.append('_ssl') # find out which version of OpenSSL we have openssl_ver = 0 @@ -578,6 +631,7 @@ include_dirs = ssl_incs, library_dirs = ssl_libs, libraries = ['ssl', 'crypto']) ) + missing.extend(['_sha', '_md5']) else: # The _sha module implements the SHA1 hash algorithm. exts.append( Extension('_sha', ['shamodule.c']) ) @@ -587,12 +641,14 @@ exts.append( Extension('_md5', sources = ['md5module.c', 'md5.c'], depends = ['md5.h']) ) + missing.append('_hashlib') if (openssl_ver < 0x00908000): # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash exts.append( Extension('_sha256', ['sha256module.c']) ) exts.append( Extension('_sha512', ['sha512module.c']) ) - + else: + missing.extend(['_sha256', '_sha512']) # Modules that provide persistent dictionary-like semantics. You will # probably want to arrange for at least one of them to be available on @@ -618,10 +674,11 @@ '/usr/include/db4', '/usr/local/include/db4', '/opt/sfw/include/db4', - '/sw/include/db4', '/usr/include/db3', '/usr/local/include/db3', '/opt/sfw/include/db3', + # Fink defaults (http://fink.sourceforge.net/) + '/sw/include/db4', '/sw/include/db3', ] # 4.x minor number specific paths @@ -632,6 +689,8 @@ db_inc_paths.append('/usr/local/include/db4%d' % x) db_inc_paths.append('/pkg/db-4.%d/include' % x) db_inc_paths.append('/opt/db-4.%d/include' % x) + # MacPorts default (http://www.macports.org/) + db_inc_paths.append('/opt/local/include/db4%d' % x) # 3.x minor number specific paths for x in (3,): db_inc_paths.append('/usr/include/db3%d' % x) @@ -656,7 +715,7 @@ std_variants.append(os.path.join(dn, "db3.%d"%x)) db_inc_paths = std_variants + db_inc_paths - + db_inc_paths = [p for p in db_inc_paths if os.path.exists(p)] db_ver_inc_map = {} @@ -679,7 +738,7 @@ if ( (db_ver not in db_ver_inc_map) and (db_ver <= max_db_ver and db_ver >= min_db_ver) ): # save the include directory with the db.h version - # (first occurrance only) + # (first occurrence only) db_ver_inc_map[db_ver] = d if db_setup_debug: print("db.h: found", db_ver, "in", d) @@ -688,7 +747,8 @@ if db_setup_debug: print("db.h: ignoring", d) else: # ignore this header, it didn't contain a version number - if db_setup_debug: print("db.h: unsupported version", db_ver, "in", d) + if db_setup_debug: + print("db.h: no version number version in", d) db_found_vers = sorted(db_ver_inc_map.keys()) @@ -698,10 +758,8 @@ # check lib directories parallel to the location of the header db_dirs_to_check = [ - os.path.join(db_incdir, '..', 'lib64'), - os.path.join(db_incdir, '..', 'lib'), - os.path.join(db_incdir, '..', '..', 'lib64'), - os.path.join(db_incdir, '..', '..', 'lib'), + db_incdir.replace("include", 'lib64'), + db_incdir.replace("include", 'lib'), ] db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check) @@ -742,6 +800,7 @@ db_incs = None dblibs = [] dblib_dir = None + missing.append('_bsddb') # The sqlite interface sqlite_setup_debug = False # verbose debug prints from this script? @@ -834,6 +893,8 @@ runtime_library_dirs=sqlite_libdir, extra_link_args=sqlite_extra_link_args, libraries=["sqlite3",])) + else: + missing.append('_sqlite3') # Look for Berkeley db 1.85. Note that it is built as a different # module name so it can be included even when later versions are @@ -856,6 +917,10 @@ libraries=libraries)) else: exts.append(Extension('bsddb185', ['bsddbmodule.c'])) + else: + missing.append('bsddb185') + else: + missing.append('bsddb185') # The standard Unix dbm module: if platform not in ['cygwin']: @@ -881,11 +946,15 @@ define_macros=[('HAVE_BERKDB_H',None), ('DB_DBM_HSEARCH',None)], libraries=dblibs)) + else: + missing.append('dbm') # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: if (self.compiler.find_library_file(lib_dirs, 'gdbm')): exts.append( Extension('gdbm', ['gdbmmodule.c'], libraries = ['gdbm'] ) ) + else: + missing.append('gdbm') # Unix-only modules if platform not in ['mac', 'win32']: @@ -894,6 +963,8 @@ # Jeremy Hylton's rlimit interface if platform not in ['atheos']: exts.append( Extension('resource', ['resource.c']) ) + else: + missing.append('resource') # Sun yellow pages. Some systems have the functions in libc. if platform not in ['cygwin', 'atheos']: @@ -903,6 +974,10 @@ libs = [] exts.append( Extension('nis', ['nismodule.c'], libraries = libs) ) + else: + missing.append('nis') + else: + missing.extend(['nis', 'resource', 'termios']) # Curses support, requiring the System V version of curses, often # provided by the ncurses library. @@ -931,13 +1006,16 @@ exts.append( Extension('_curses', ['_cursesmodule.c'], libraries = curses_libs) ) + else: + missing.append('_curses') # If the curses module is enabled, check for the panel module if (module_enabled(exts, '_curses') and self.compiler.find_library_file(lib_dirs, panel_library)): exts.append( Extension('_curses_panel', ['_curses_panel.c'], libraries = [panel_library] + curses_libs) ) - + else: + missing.append('_curses_panel') # Andrew Kuchling's zlib module. Note that some versions of zlib # 1.1.3 have security problems. See CERT Advisory CA-2002-07: @@ -973,6 +1051,12 @@ exts.append( Extension('zlib', ['zlibmodule.c'], libraries = ['z'], extra_link_args = zlib_extra_link_args)) + else: + missing.append('zlib') + else: + missing.append('zlib') + else: + missing.append('zlib') # Gustavo Niemeyer's bz2 module. if (self.compiler.find_library_file(lib_dirs, 'bz2')): @@ -983,6 +1067,8 @@ exts.append( Extension('bz2', ['bz2module.c'], libraries = ['bz2'], extra_link_args = bz2_extra_link_args) ) + else: + missing.append('bz2') # Interface to the Expat XML parser # @@ -1020,14 +1106,20 @@ include_dirs = [expatinc], sources = ['_elementtree.c'], )) + else: + missing.append('_elementtree') # Hye-Shik Chang's CJKCodecs modules. if have_unicode: exts.append(Extension('_multibytecodec', ['cjkcodecs/multibytecodec.c'])) for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'): - exts.append(Extension('_codecs_' + loc, + exts.append(Extension('_codecs_%s' % loc, ['cjkcodecs/_codecs_%s.c' % loc])) + else: + missing.append('_multibytecodec') + for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'): + missing.append('_codecs_%s' % loc) # Dynamic loading module if sys.maxint == 0x7fffffff: @@ -1035,6 +1127,10 @@ dl_inc = find_file('dlfcn.h', [], inc_dirs) if (dl_inc is not None) and (platform not in ['atheos']): exts.append( Extension('dl', ['dlmodule.c']) ) + else: + missing.append('dl') + else: + missing.append('dl') # Thomas Heller's _ctypes module self.detect_ctypes(inc_dirs, lib_dirs) @@ -1046,14 +1142,20 @@ if platform == 'linux2': # Linux-specific modules exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) ) + else: + missing.append('linuxaudiodev') if platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6', 'freebsd7'): exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) ) + else: + missing.append('ossaudiodev') if platform == 'sunos5': # SunOS specific modules exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) ) + else: + missing.append('sunaudiodev') if platform == 'darwin' and ("--disable-toolbox-glue" not in sysconfig.get_config_var("CONFIG_ARGS")): @@ -1142,6 +1244,11 @@ # Call the method for detecting whether _tkinter can be compiled self.detect_tkinter(inc_dirs, lib_dirs) + if '_tkinter' not in [e.name for e in self.extensions]: + missing.append('_tkinter') + + return missing + def detect_tkinter_darwin(self, inc_dirs, lib_dirs): # The _tkinter module, using frameworks. Since frameworks are quite # different the UNIX search logic is not sharable. From python-checkins at python.org Fri Apr 27 22:07:17 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 27 Apr 2007 22:07:17 +0200 (CEST) Subject: [Python-checkins] r55006 - peps/trunk/pep-3119.txt Message-ID: <20070427200717.905D21E4006@bag.python.org> Author: guido.van.rossum Date: Fri Apr 27 22:07:16 2007 New Revision: 55006 Modified: peps/trunk/pep-3119.txt Log: Fix typos and nits reported by various correspondents, add a few clarifications and new open issues. Only the easy stuff. Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Fri Apr 27 22:07:16 2007 @@ -183,6 +183,11 @@ useful as an end-point for a super-call in framework using a cooperative multiple-inheritance [7]_, [8]_. +**Open issues:** Should we also provide a standard way to declare +abstract data attributes? If so, how should these be spelled? +Perhaps place ``@abstractattribute`` decorators on properties? Or use +an ``@attributes(name1, name2, ...)`` class decorator? + Overloading ``isinstance()`` and ``issubclass()`` ------------------------------------------------- @@ -213,7 +218,7 @@ functions ``isinstance()`` and ``issubclass()``. The overloading works as follows: The call ``isinstance(x, C)`` first checks whether ``C.__instancecheck__`` exists, and if so, calls -``C.__subclasscheck__(x)`` instead of its normal implementation. +``C.__instancecheck__(x)`` instead of its normal implementation. Similarly, the call ``issubclass(D, C)`` first checks whether ``C.__subclasscheck__`` exists, and if so, calls ``C.__subclasscheck__(D)`` instead of its normal implementation. @@ -272,11 +277,12 @@ itself, fulfilling an important invariant of iterators (which in Python 2 has to be implemented anew by each iterator class). -No ABCs override ``__init__``, ``__new__``, ``__str__`` or -``__repr__``. Defining a standard constructor signature would -unnecessarily constrain custom container types, for example Patricia -trees or gdbm files. Defining a specific string representation for a -collection is similarly left up to individual implementations. +No ABCs defined in the PEP override ``__init__``, ``__new__``, +``__str__`` or ``__repr__``. Defining a standard constructor +signature would unnecessarily constrain custom container types, for +example Patricia trees or gdbm files. Defining a specific string +representation for a collection is similarly left up to individual +implementations. Ordering ABCs @@ -328,6 +334,8 @@ **Note:** being an instance of this class does not imply that an object is immutable; e.g. a tuple containing a list as a member is not immutable; its ``__hash__`` method raises ``TypeError``. + (This is because it recursively tries to compute the hash of each + member; if a member is unhashable it raises ``TypeError``.) ``Iterable`` The base class for classes defining ``__iter__``. The @@ -357,18 +365,20 @@ ``Iterable``, then ``(x in o for x in o)`` should be a generator yielding only True values for any instance ``o`` of ``C``. - **Note:** strictly speaking, there are three variants of this method's - semantics. The first one is for sets and mappings, which is fast: - O(1) or O(log N). The second one is for membership checking on - sequences, which is slow: O(N). The third one is for subsequence - checking on (character or byte) strings, which is also slow: O(N). - Would it make sense to distinguish these? The signature of the - third variant is different, since it takes a sequence (typically - of the same type as the method's target) intead of an element. - For now, I'm using the same type for all three. This means that - is is possible for ``x in o`` to be True even though ``x`` is - never yielded by ``iter(o)``. A suggested name for the third form - is ``Searchable``. + **Open issues:** strictly speaking, there are three variants of + this method's semantics. The first one is for sets and mappings, + which is fast: O(1) or O(log N). The second one is for membership + checking on sequences, which is slow: O(N). The third one is for + subsequence checking on (character or byte) strings, which is also + slow: O(N). Would it make sense to distinguish these? The + signature of the third variant is different, since it takes a + sequence (typically of the same type as the method's target) + intead of an element. For now, I'm using the same type for all + three. This means that is is possible for ``x in o`` to be True + even though ``x`` is never yielded by ``iter(o)``. A suggested + name for the third form is ``Searchable`` (though people have + objected against this name on the grounds that it has the wrong + association). Sets @@ -489,9 +499,10 @@ implementation raises ``NotImplementedError``. ``.pop()`` - Concrete method that removes an arbitrary item. If the set is - empty, it raises ``KeyError``. The default implementation - removes the first item returned by the set's iterator. + Concrete method that removes and returns an arbitrary item. + If the set is empty, it raises ``KeyError``. The default + implementation removes the first item returned by the set's + iterator. ``.toggle(x)`` Concrete method returning a ``bool`` that adds x to the set if @@ -543,7 +554,7 @@ Concrete method returning ``self[key]`` if this does not raise ``KeyError``, and the ``default`` value if it does. - ``.__contains__()`` + ``.__contains__(key)`` Concrete method returning ``True`` if ``self[key]`` does not raise ``KeyError``, and ``False`` if it does. @@ -553,42 +564,44 @@ are also referred to as items. The items also form a set. Methods: - ``__len__`` + ``.__len__()`` Abstract method returning the length of the key set. - ``__iter__`` + ``.__iter__()`` Abstract method returning each key in the key set exactly once. - ``__eq__`` + ``.__eq__(obj)`` Concrete method for comparing mappings. Two mappings, even with different implementations, can be compared for equality, - and are considered equal if and only iff their item sets are + and are considered equal if and only if their item sets are equal. **Open issues:** should we define comparison of instances of different concrete mapping types this way? - ``keys`` + ``.keys()`` Concrete method returning the key set as a ``Set``. The default concrete implementation returns a "view" on the key set (meaning if the underlying mapping is modified, the view's value changes correspondingly); subclasses are not required to return a view but they should return a ``Set``. - ``items`` + ``.items()`` Concrete method returning the items as a ``Set``. The default concrete implementation returns a "view" on the item set; subclasses are not required to return a view but they should return a ``Set``. - ``values`` + ``.values()`` Concrete method returning the values as a sized, iterable container (not a set!). The default concrete implementation returns a "view" on the values of the mapping; subclasses are not required to return a view but they should return a sized, iterable container. - The following invariant should hold for any mapping ``m``:: + The following invariants should hold for any mapping ``m``:: - list(m.items()) == list(zip(m.keys(), m.values())) + len(m.values()) == len(m.keys()) == len(m.items()) == len(m) + [value for value in m.values()] == [m[key] for key in m.keys()] + [item for item in m.items()] == [(key, m[key]) for key in m.keys()] i.e. iterating over the items, keys and values should return results in the same order. From python-checkins at python.org Fri Apr 27 22:16:23 2007 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 27 Apr 2007 22:16:23 +0200 (CEST) Subject: [Python-checkins] r55007 - python/branches/py3k-struni Message-ID: <20070427201623.921991E4006@bag.python.org> Author: guido.van.rossum Date: Fri Apr 27 22:16:19 2007 New Revision: 55007 Added: python/branches/py3k-struni/ - copied from r55006, python/branches/p3yk/ Log: Start working on the str/unicode unification. From python-checkins at python.org Sat Apr 28 00:36:06 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 28 Apr 2007 00:36:06 +0200 (CEST) Subject: [Python-checkins] r55008 - in python/branches/release25-maint: Doc/lib/libstdtypes.tex Misc/NEWS Message-ID: <20070427223606.7926A1E400B@bag.python.org> Author: brett.cannon Date: Sat Apr 28 00:35:57 2007 New Revision: 55008 Modified: python/branches/release25-maint/Doc/lib/libstdtypes.tex python/branches/release25-maint/Misc/NEWS Log: Backport r54712: document that calling file.next() on a file open for writing leads to undefined behaviour. Modified: python/branches/release25-maint/Doc/lib/libstdtypes.tex ============================================================================== --- python/branches/release25-maint/Doc/lib/libstdtypes.tex (original) +++ python/branches/release25-maint/Doc/lib/libstdtypes.tex Sat Apr 28 00:35:57 2007 @@ -1615,14 +1615,15 @@ iterator, typically in a \keyword{for} loop (for example, \code{for line in f: print line}), the \method{next()} method is called repeatedly. This method returns the next input line, or raises -\exception{StopIteration} when \EOF{} is hit. In order to make a -\keyword{for} loop the most efficient way of looping over the lines of -a file (a very common operation), the \method{next()} method uses a -hidden read-ahead buffer. As a consequence of using a read-ahead -buffer, combining \method{next()} with other file methods (like -\method{readline()}) does not work right. However, using -\method{seek()} to reposition the file to an absolute position will -flush the read-ahead buffer. +\exception{StopIteration} when \EOF{} is hit when the file is open for +reading (behavior is undefined when the file is open for writing). In +order to make a \keyword{for} loop the most efficient way of looping +over the lines of a file (a very common operation), the +\method{next()} method uses a hidden read-ahead buffer. As a +consequence of using a read-ahead buffer, combining \method{next()} +with other file methods (like \method{readline()}) does not work +right. However, using \method{seek()} to reposition the file to an +absolute position will flush the read-ahead buffer. \versionadded{2.3} \end{methoddesc} Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Sat Apr 28 00:35:57 2007 @@ -25,6 +25,13 @@ run in verbose mode. +Documentation +------------- + +- Bug #1569057: Document that calling file.next() on a file open for writing + has undefined behaviour. Backport of r54712. + + What's New in Python 2.5.1? ============================= From python-checkins at python.org Sat Apr 28 00:40:08 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 28 Apr 2007 00:40:08 +0200 (CEST) Subject: [Python-checkins] r55009 - sandbox/trunk/import_in_py/importlib.py Message-ID: <20070427224008.6ECA31E4008@bag.python.org> Author: brett.cannon Date: Sat Apr 28 00:40:04 2007 New Revision: 55009 Modified: sandbox/trunk/import_in_py/importlib.py Log: Fix a misspelling. Modified: sandbox/trunk/import_in_py/importlib.py ============================================================================== --- sandbox/trunk/import_in_py/importlib.py (original) +++ sandbox/trunk/import_in_py/importlib.py Sat Apr 28 00:40:04 2007 @@ -814,7 +814,7 @@ def _return_module(self, absolute_name, relative_name, fromlist): """Return the proper module based on what module was requested (and its - absolute module name), who is requesting it, and whether any speicific + absolute module name), who is requesting it, and whether any specific attributes were specified. The semantics of this method revolve around 'fromlist'. When it is From python-checkins at python.org Sat Apr 28 00:51:44 2007 From: python-checkins at python.org (andrew.kuchling) Date: Sat, 28 Apr 2007 00:51:44 +0200 (CEST) Subject: [Python-checkins] r55010 - peps/trunk/pep-0249.txt Message-ID: <20070427225144.366801E401E@bag.python.org> Author: andrew.kuchling Date: Sat Apr 28 00:51:38 2007 New Revision: 55010 Modified: peps/trunk/pep-0249.txt Log: Fix 'the the' error Modified: peps/trunk/pep-0249.txt ============================================================================== --- peps/trunk/pep-0249.txt (original) +++ peps/trunk/pep-0249.txt Sat Apr 28 00:51:38 2007 @@ -226,7 +226,7 @@ transaction support. [3] In case a database does provide transactions this method - causes the the database to roll back to the start of any + causes the database to roll back to the start of any pending transaction. Closing a connection without committing the changes first will cause an implicit rollback to be performed. @@ -573,7 +573,7 @@ * The preferred object type for Binary objects are the buffer types available in standard Python starting with version 1.5.2. Please see the Python documentation for - details. For information about the the C interface have a + details. For information about the C interface have a look at Include/bufferobject.h and Objects/bufferobject.c in the Python source distribution. From python-checkins at python.org Sat Apr 28 01:17:50 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 28 Apr 2007 01:17:50 +0200 (CEST) Subject: [Python-checkins] r55011 - in python/branches/release25-maint: Lib/_strptime.py Lib/test/test_strptime.py Misc/NEWS Message-ID: <20070427231750.D29F41E4008@bag.python.org> Author: brett.cannon Date: Sat Apr 28 01:17:43 2007 New Revision: 55011 Modified: python/branches/release25-maint/Lib/_strptime.py python/branches/release25-maint/Lib/test/test_strptime.py python/branches/release25-maint/Misc/NEWS Log: Backport fix for r54646-7: properly clear locale cache in time.strptime when the locale changes between calls. Modified: python/branches/release25-maint/Lib/_strptime.py ============================================================================== --- python/branches/release25-maint/Lib/_strptime.py (original) +++ python/branches/release25-maint/Lib/_strptime.py Sat Apr 28 01:17:43 2007 @@ -299,17 +299,16 @@ global _TimeRE_cache, _regex_cache _cache_lock.acquire() try: - time_re = _TimeRE_cache - locale_time = time_re.locale_time - if _getlang() != locale_time.lang: + if _getlang() != _TimeRE_cache.locale_time.lang: _TimeRE_cache = TimeRE() - _regex_cache = {} + _regex_cache.clear() if len(_regex_cache) > _CACHE_MAX_SIZE: _regex_cache.clear() + locale_time = _TimeRE_cache.locale_time format_regex = _regex_cache.get(format) if not format_regex: try: - format_regex = time_re.compile(format) + format_regex = _TimeRE_cache.compile(format) # KeyError raised when a bad format is found; can be specified as # \\, in which case it was a stray % but with a space after it except KeyError, err: Modified: python/branches/release25-maint/Lib/test/test_strptime.py ============================================================================== --- python/branches/release25-maint/Lib/test/test_strptime.py (original) +++ python/branches/release25-maint/Lib/test/test_strptime.py Sat Apr 28 01:17:43 2007 @@ -505,6 +505,35 @@ self.failIfEqual(locale_time_id, id(_strptime._TimeRE_cache.locale_time)) + def test_TimeRE_recreation(self): + # The TimeRE instance should be recreated upon changing the locale. + locale_info = locale.getlocale(locale.LC_TIME) + try: + locale.setlocale(locale.LC_TIME, ('en_US', 'UTF8')) + except locale.Error: + return + try: + _strptime.strptime('10', '%d') + # Get id of current cache object. + first_time_re_id = id(_strptime._TimeRE_cache) + try: + # Change the locale and force a recreation of the cache. + locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8')) + _strptime.strptime('10', '%d') + # Get the new cache object's id. + second_time_re_id = id(_strptime._TimeRE_cache) + # They should not be equal. + self.failIfEqual(first_time_re_id, second_time_re_id) + # Possible test locale is not supported while initial locale is. + # If this is the case just suppress the exception and fall-through + # to the reseting to the original locale. + except locale.Error: + pass + # Make sure we don't trample on the locale setting once we leave the + # test. + finally: + locale.setlocale(locale.LC_TIME, locale_info) + def test_main(): test_support.run_unittest( Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Sat Apr 28 01:17:43 2007 @@ -12,6 +12,9 @@ Library ------- +- Bug #1290505: Properly clear time.strptime's locale cache when the locale + changes between calls. Backport of r54646 and r54647. + - Bug #1706381: Specifying the SWIG option "-c++" in the setup.py file (as opposed to the command line) will now write file names ending in ".cpp" too. From buildbot at python.org Sat Apr 28 01:25:53 2007 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Apr 2007 23:25:53 +0000 Subject: [Python-checkins] buildbot failure in alpha Tru64 5.1 2.5 Message-ID: <20070427232553.9024E1E4008@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%25202.5/builds/251 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: brett.cannon,fred.drake,georg.brandl BUILD FAILED: failed compile sincerely, -The Buildbot From python-checkins at python.org Sat Apr 28 01:42:12 2007 From: python-checkins at python.org (andrew.kuchling) Date: Sat, 28 Apr 2007 01:42:12 +0200 (CEST) Subject: [Python-checkins] r55012 - peps/trunk/pep-3119.txt Message-ID: <20070427234212.AF2C21E4008@bag.python.org> Author: andrew.kuchling Date: Sat Apr 28 01:42:06 2007 New Revision: 55012 Modified: peps/trunk/pep-3119.txt Log: Fix 'the the' error Modified: peps/trunk/pep-3119.txt ============================================================================== --- peps/trunk/pep-3119.txt (original) +++ peps/trunk/pep-3119.txt Sat Apr 28 01:42:06 2007 @@ -76,7 +76,7 @@ encapsulated within an object, examples being rule or pattern-match driven logic. -On the the other hand, one of the criticisms of inspection by classic +On the other hand, one of the criticisms of inspection by classic OOP theorists is the lack of formalisms and the ad hoc nature of what is being inspected. In a language such as Python, in which almost any aspect of an object can be reflected and directly accessed by external From python-checkins at python.org Sat Apr 28 01:54:18 2007 From: python-checkins at python.org (guido.van.rossum) Date: Sat, 28 Apr 2007 01:54:18 +0200 (CEST) Subject: [Python-checkins] r55013 - in python/branches/py3k-struni: Include/pydebug.h Lib/distutils/ccompiler.py Lib/distutils/cmd.py Lib/distutils/command/build_clib.py Lib/distutils/command/build_ext.py Lib/distutils/command/build_py.py Lib/distutils/command/config.py Lib/distutils/command/install.py Lib/distutils/command/install_data.py Lib/distutils/dir_util.py Lib/distutils/dist.py Lib/distutils/extension.py Lib/distutils/fancy_getopt.py Lib/distutils/filelist.py Lib/distutils/unixccompiler.py Lib/locale.py Lib/os.py Lib/sre_compile.py Lib/test/test_builtin.py Modules/posixmodule.c Objects/moduleobject.c Objects/unicodeobject.c Python/ast.c Python/bltinmodule.c Python/ceval.c Python/getargs.c Python/import.c Python/pythonrun.c Message-ID: <20070427235418.1784B1E4008@bag.python.org> Author: guido.van.rossum Date: Sat Apr 28 01:53:51 2007 New Revision: 55013 Modified: python/branches/py3k-struni/Include/pydebug.h python/branches/py3k-struni/Lib/distutils/ccompiler.py python/branches/py3k-struni/Lib/distutils/cmd.py python/branches/py3k-struni/Lib/distutils/command/build_clib.py python/branches/py3k-struni/Lib/distutils/command/build_ext.py python/branches/py3k-struni/Lib/distutils/command/build_py.py python/branches/py3k-struni/Lib/distutils/command/config.py python/branches/py3k-struni/Lib/distutils/command/install.py python/branches/py3k-struni/Lib/distutils/command/install_data.py python/branches/py3k-struni/Lib/distutils/dir_util.py python/branches/py3k-struni/Lib/distutils/dist.py python/branches/py3k-struni/Lib/distutils/extension.py python/branches/py3k-struni/Lib/distutils/fancy_getopt.py python/branches/py3k-struni/Lib/distutils/filelist.py python/branches/py3k-struni/Lib/distutils/unixccompiler.py python/branches/py3k-struni/Lib/locale.py python/branches/py3k-struni/Lib/os.py python/branches/py3k-struni/Lib/sre_compile.py python/branches/py3k-struni/Lib/test/test_builtin.py python/branches/py3k-struni/Modules/posixmodule.c python/branches/py3k-struni/Objects/moduleobject.c python/branches/py3k-struni/Objects/unicodeobject.c python/branches/py3k-struni/Python/ast.c python/branches/py3k-struni/Python/bltinmodule.c python/branches/py3k-struni/Python/ceval.c python/branches/py3k-struni/Python/getargs.c python/branches/py3k-struni/Python/import.c python/branches/py3k-struni/Python/pythonrun.c Log: Checkpoint. Manipulated things so that string literals are always unicode, and a few other compensating changes, e.g. str <- unicode, chr <- unichr, and repr() of a unicode string no longer starts with 'u'. Lots of unit tests are broken, but some basic things work, in particular distutils works so the extensions can be built, and test_builtin.py works. Modified: python/branches/py3k-struni/Include/pydebug.h ============================================================================== --- python/branches/py3k-struni/Include/pydebug.h (original) +++ python/branches/py3k-struni/Include/pydebug.h Sat Apr 28 01:53:51 2007 @@ -14,7 +14,6 @@ PyAPI_DATA(int) Py_UseClassExceptionsFlag; PyAPI_DATA(int) Py_FrozenFlag; PyAPI_DATA(int) Py_TabcheckFlag; -PyAPI_DATA(int) Py_UnicodeFlag; PyAPI_DATA(int) Py_IgnoreEnvironmentFlag; PyAPI_DATA(int) Py_DivisionWarningFlag; Modified: python/branches/py3k-struni/Lib/distutils/ccompiler.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/ccompiler.py (original) +++ python/branches/py3k-struni/Lib/distutils/ccompiler.py Sat Apr 28 01:53:51 2007 @@ -168,7 +168,7 @@ # set_executables () def set_executable(self, key, value): - if type(value) is StringType: + if isinstance(value, basestring): setattr(self, key, split_quoted(value)) else: setattr(self, key, value) @@ -193,8 +193,8 @@ if not (type (defn) is TupleType and (len (defn) == 1 or (len (defn) == 2 and - (type (defn[1]) is StringType or defn[1] is None))) and - type (defn[0]) is StringType): + (isinstance (defn[1], basestring) or defn[1] is None))) and + isinstance (defn[0], basestring)): raise TypeError, \ ("invalid macro definition '%s': " % defn) + \ "must be tuple (string,), (string, string), or " + \ @@ -344,7 +344,7 @@ """ if outdir is None: outdir = self.output_dir - elif type(outdir) is not StringType: + elif not isinstance(outdir, basestring): raise TypeError, "'output_dir' must be a string or None" if macros is None: @@ -442,7 +442,7 @@ """ if output_dir is None: output_dir = self.output_dir - elif type (output_dir) is not StringType: + elif not isinstance(output_dir, basestring): raise TypeError, "'output_dir' must be a string or None" if macros is None: @@ -527,7 +527,7 @@ if output_dir is None: output_dir = self.output_dir - elif type (output_dir) is not StringType: + elif not isinstance(output_dir, basestring): raise TypeError, "'output_dir' must be a string or None" return (objects, output_dir) Modified: python/branches/py3k-struni/Lib/distutils/cmd.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/cmd.py (original) +++ python/branches/py3k-struni/Lib/distutils/cmd.py Sat Apr 28 01:53:51 2007 @@ -222,7 +222,7 @@ if val is None: setattr(self, option, default) return default - elif type(val) is not StringType: + elif not isinstance(val, basestring): raise DistutilsOptionError, \ "'%s' must be a %s (got `%s`)" % (option, what, val) return val @@ -242,12 +242,11 @@ val = getattr(self, option) if val is None: return - elif type(val) is StringType: + elif isinstance(val, basestring): setattr(self, option, re.split(r',\s*|\s+', val)) else: if type(val) is ListType: - types = map(type, val) - ok = (types == [StringType] * len(val)) + ok = all(isinstance(v, basestring) for v in val) else: ok = 0 @@ -421,7 +420,7 @@ # Allow 'infiles' to be a single string - if type(infiles) is StringType: + if isinstance(infiles, basestring): infiles = (infiles,) elif type(infiles) not in (ListType, TupleType): raise TypeError, \ Modified: python/branches/py3k-struni/Lib/distutils/command/build_clib.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/command/build_clib.py (original) +++ python/branches/py3k-struni/Lib/distutils/command/build_clib.py Sat Apr 28 01:53:51 2007 @@ -92,7 +92,7 @@ if self.include_dirs is None: self.include_dirs = self.distribution.include_dirs or [] - if type(self.include_dirs) is StringType: + if isinstance(self.include_dirs, basestring): self.include_dirs = self.include_dirs.split(os.pathsep) # XXX same as for build_ext -- what about 'self.define' and @@ -147,7 +147,7 @@ raise DistutilsSetupError, \ "each element of 'libraries' must a 2-tuple" - if type(lib[0]) is not StringType: + if isinstance(lib[0], basestring) StringType: raise DistutilsSetupError, \ "first element of each tuple in 'libraries' " + \ "must be a string (the library name)" Modified: python/branches/py3k-struni/Lib/distutils/command/build_ext.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/command/build_ext.py (original) +++ python/branches/py3k-struni/Lib/distutils/command/build_ext.py Sat Apr 28 01:53:51 2007 @@ -137,7 +137,7 @@ plat_py_include = sysconfig.get_python_inc(plat_specific=1) if self.include_dirs is None: self.include_dirs = self.distribution.include_dirs or [] - if type(self.include_dirs) is StringType: + if isinstance(self.include_dirs, basestring): self.include_dirs = self.include_dirs.split(os.pathsep) # Put the Python "system" include dir at the end, so that @@ -146,7 +146,7 @@ if plat_py_include != py_include: self.include_dirs.append(plat_py_include) - if type(self.libraries) is StringType: + if isinstance(self.libraries, basestring): self.libraries = [self.libraries] # Life is easier if we're not forever checking for None, so @@ -155,12 +155,12 @@ self.libraries = [] if self.library_dirs is None: self.library_dirs = [] - elif type(self.library_dirs) is StringType: + elif isinstance(self.library_dirs, basestring): self.library_dirs = self.library_dirs.split(os.pathsep) if self.rpath is None: self.rpath = [] - elif type(self.rpath) is StringType: + elif isinstance(self.rpath, basestring): self.rpath = self.rpath.split(os.pathsep) # for extensions under windows use different directories @@ -321,7 +321,7 @@ ("each element of 'ext_modules' option must be an " "Extension instance or 2-tuple") - if not (type(ext_name) is StringType and + if not (isinstance(ext_name, basestring) and extension_name_re.match(ext_name)): raise DistutilsSetupError, \ ("first element of each tuple in 'ext_modules' " Modified: python/branches/py3k-struni/Lib/distutils/command/build_py.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/command/build_py.py (original) +++ python/branches/py3k-struni/Lib/distutils/command/build_py.py Sat Apr 28 01:53:51 2007 @@ -361,7 +361,7 @@ def build_module (self, module, module_file, package): - if type(package) is StringType: + if isinstance(package, basestring): package = package.split('.') elif type(package) not in (ListType, TupleType): raise TypeError, \ Modified: python/branches/py3k-struni/Lib/distutils/command/config.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/command/config.py (original) +++ python/branches/py3k-struni/Lib/distutils/command/config.py Sat Apr 28 01:53:51 2007 @@ -73,17 +73,17 @@ def finalize_options (self): if self.include_dirs is None: self.include_dirs = self.distribution.include_dirs or [] - elif type(self.include_dirs) is StringType: + elif isinstance(self.include_dirs, basestring): self.include_dirs = self.include_dirs.split(os.pathsep) if self.libraries is None: self.libraries = [] - elif type(self.libraries) is StringType: + elif isinstance(self.libraries, basestring): self.libraries = [self.libraries] if self.library_dirs is None: self.library_dirs = [] - elif type(self.library_dirs) is StringType: + elif isinstance(self.library_dirs, basestring): self.library_dirs = self.library_dirs.split(os.pathsep) @@ -212,7 +212,7 @@ self._check_compiler() (src, out) = self._preprocess(body, headers, include_dirs, lang) - if type(pattern) is StringType: + if isinstance(pattern, basestring): pattern = re.compile(pattern) file = open(out) Modified: python/branches/py3k-struni/Lib/distutils/command/install.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/command/install.py (original) +++ python/branches/py3k-struni/Lib/distutils/command/install.py Sat Apr 28 01:53:51 2007 @@ -463,7 +463,7 @@ self.extra_path = self.distribution.extra_path if self.extra_path is not None: - if type(self.extra_path) is StringType: + if isinstance(self.extra_path, basestring): self.extra_path = self.extra_path.split(',') if len(self.extra_path) == 1: Modified: python/branches/py3k-struni/Lib/distutils/command/install_data.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/command/install_data.py (original) +++ python/branches/py3k-struni/Lib/distutils/command/install_data.py Sat Apr 28 01:53:51 2007 @@ -10,7 +10,6 @@ __revision__ = "$Id$" import os -from types import StringType from distutils.core import Command from distutils.util import change_root, convert_path @@ -48,7 +47,7 @@ def run (self): self.mkpath(self.install_dir) for f in self.data_files: - if type(f) is StringType: + if isinstance(f, basestring): # it's a simple file, so copy it f = convert_path(f) if self.warn_dir: Modified: python/branches/py3k-struni/Lib/distutils/dir_util.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/dir_util.py (original) +++ python/branches/py3k-struni/Lib/distutils/dir_util.py Sat Apr 28 01:53:51 2007 @@ -31,7 +31,7 @@ global _path_created # Detect a common bug -- name is None - if not isinstance(name, StringTypes): + if not isinstance(name, basestring): raise DistutilsInternalError, \ "mkpath: 'name' must be a string (got %r)" % (name,) Modified: python/branches/py3k-struni/Lib/distutils/dist.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/dist.py (original) +++ python/branches/py3k-struni/Lib/distutils/dist.py Sat Apr 28 01:53:51 2007 @@ -598,13 +598,13 @@ keywords = self.metadata.keywords if keywords is not None: - if type(keywords) is StringType: + if isinstance(keywords, basestring): keywordlist = keywords.split(',') self.metadata.keywords = [x.strip() for x in keywordlist] platforms = self.metadata.platforms if platforms is not None: - if type(platforms) is StringType: + if isinstance(platforms, basestring): platformlist = platforms.split(',') self.metadata.platforms = [x.strip() for x in platformlist] @@ -906,7 +906,7 @@ neg_opt = {} try: - is_string = type(value) is StringType + is_string = isinstance(value, basestring) if option in neg_opt and is_string: setattr(command_obj, neg_opt[option], not strtobool(value)) elif option in bool_opts and is_string: Modified: python/branches/py3k-struni/Lib/distutils/extension.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/extension.py (original) +++ python/branches/py3k-struni/Lib/distutils/extension.py Sat Apr 28 01:53:51 2007 @@ -103,9 +103,9 @@ language=None, **kw # To catch unknown keywords ): - assert type(name) is StringType, "'name' must be a string" + assert isinstance(name, basestring), "'name' must be a string" assert (type(sources) is ListType and - map(type, sources) == [StringType]*len(sources)), \ + all(isinstance(v, basestring) for v in sources)), \ "'sources' must be a list of strings" self.name = name Modified: python/branches/py3k-struni/Lib/distutils/fancy_getopt.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/fancy_getopt.py (original) +++ python/branches/py3k-struni/Lib/distutils/fancy_getopt.py Sat Apr 28 01:53:51 2007 @@ -166,13 +166,13 @@ raise ValueError, "invalid option tuple: %r" % (option,) # Type- and value-check the option names - if type(long) is not StringType or len(long) < 2: + if not isinstance(long, basestring) or len(long) < 2: raise DistutilsGetoptError, \ ("invalid long option '%s': " "must be a string of length >= 2") % long if (not ((short is None) or - (type(short) is StringType and len(short) == 1))): + (isinstance(short, basestring) and len(short) == 1))): raise DistutilsGetoptError, \ ("invalid short option '%s': " "must a single character or None") % short Modified: python/branches/py3k-struni/Lib/distutils/filelist.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/filelist.py (original) +++ python/branches/py3k-struni/Lib/distutils/filelist.py Sat Apr 28 01:53:51 2007 @@ -333,7 +333,7 @@ or just returned as-is (assumes it's a regex object). """ if is_regex: - if type(pattern) is StringType: + if isinstance(pattern, basestring): return re.compile(pattern) else: return pattern Modified: python/branches/py3k-struni/Lib/distutils/unixccompiler.py ============================================================================== --- python/branches/py3k-struni/Lib/distutils/unixccompiler.py (original) +++ python/branches/py3k-struni/Lib/distutils/unixccompiler.py Sat Apr 28 01:53:51 2007 @@ -16,7 +16,7 @@ __revision__ = "$Id$" import os, sys -from types import StringType, NoneType +from types import NoneType from copy import copy from distutils import sysconfig @@ -212,7 +212,7 @@ lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) - if type(output_dir) not in (StringType, NoneType): + if not isinstance(output_dir, (basestring, NoneType)): raise TypeError, "'output_dir' must be a string or None" if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) Modified: python/branches/py3k-struni/Lib/locale.py ============================================================================== --- python/branches/py3k-struni/Lib/locale.py (original) +++ python/branches/py3k-struni/Lib/locale.py Sat Apr 28 01:53:51 2007 @@ -470,7 +470,7 @@ category may be given as one of the LC_* values. """ - if locale and type(locale) is not type(""): + if locale and not isinstance(locale, basestring): # convert to string locale = normalize(_build_localename(locale)) return _setlocale(category, locale) Modified: python/branches/py3k-struni/Lib/os.py ============================================================================== --- python/branches/py3k-struni/Lib/os.py (original) +++ python/branches/py3k-struni/Lib/os.py Sat Apr 28 01:53:51 2007 @@ -733,8 +733,8 @@ _urandomfd = open("/dev/urandom", O_RDONLY) except (OSError, IOError): raise NotImplementedError("/dev/urandom (or equivalent) not found") - bytes = "" - while len(bytes) < n: - bytes += read(_urandomfd, n - len(bytes)) + bs = b"" + while len(bs) < n: + bs += read(_urandomfd, n - len(bs)) close(_urandomfd) - return bytes + return bs Modified: python/branches/py3k-struni/Lib/sre_compile.py ============================================================================== --- python/branches/py3k-struni/Lib/sre_compile.py (original) +++ python/branches/py3k-struni/Lib/sre_compile.py Sat Apr 28 01:53:51 2007 @@ -470,18 +470,8 @@ _compile_charset(charset, flags, code) code[skip] = len(code) - skip -try: - unicode -except NameError: - STRING_TYPES = (type(""),) -else: - STRING_TYPES = (type(""), type(unicode(""))) - def isstring(obj): - for tp in STRING_TYPES: - if isinstance(obj, tp): - return 1 - return 0 + return isinstance(obj, basestring) def _code(p, flags): Modified: python/branches/py3k-struni/Lib/test/test_builtin.py ============================================================================== --- python/branches/py3k-struni/Lib/test/test_builtin.py (original) +++ python/branches/py3k-struni/Lib/test/test_builtin.py Sat Apr 28 01:53:51 2007 @@ -82,7 +82,7 @@ (unicode('100'), 100), (unicode('314'), 314), (unicode(' 314'), 314), - (unicode('\u0663\u0661\u0664 ','raw-unicode-escape'), 314), + (unicode(b'\u0663\u0661\u0664 ','raw-unicode-escape'), 314), (unicode(' \t\t 314 \t\t '), 314), (unicode(' 1x'), ValueError), (unicode(' 1 '), 1), @@ -185,7 +185,7 @@ self.assertEqual(chr(65), 'A') self.assertEqual(chr(97), 'a') self.assertEqual(chr(0xff), '\xff') - self.assertRaises(ValueError, chr, 256) + self.assertRaises(ValueError, chr, 1<<24) self.assertRaises(TypeError, chr) def XXX_test_cmp(self): @@ -209,7 +209,7 @@ def test_compile(self): compile('print(1)\n', '', 'exec') bom = '\xef\xbb\xbf' - compile(bom + 'print(1)\n', '', 'exec') + compile((bom + 'print(1)\n').encode("latin-1"), '', 'exec') compile(source='pass', filename='?', mode='exec') compile(dont_inherit=0, filename='tmp', source='0', mode='eval') compile('pass', '?', dont_inherit=1, mode='exec') @@ -220,7 +220,7 @@ self.assertRaises(TypeError, compile, 'pass', '?', 'exec', mode='eval', source='0', filename='tmp') if have_unicode: - compile(unicode('print(u"\xc3\xa5")\n', 'utf8'), '', 'exec') + compile(unicode(b'print(u"\xc3\xa5")\n', 'utf8'), '', 'exec') self.assertRaises(TypeError, compile, unichr(0), 'f', 'exec') self.assertRaises(ValueError, compile, unicode('a = 1'), 'f', 'bad') @@ -339,9 +339,9 @@ self.assertEqual(eval(unicode('b'), globals, locals), 200) self.assertEqual(eval(unicode('c'), globals, locals), 300) bom = '\xef\xbb\xbf' - self.assertEqual(eval(bom + 'a', globals, locals), 1) - self.assertEqual(eval(unicode('u"\xc3\xa5"', 'utf8'), globals), - unicode('\xc3\xa5', 'utf8')) + self.assertEqual(eval((bom + 'a').encode("latin-1"), globals, locals), 1) + self.assertEqual(eval(unicode(b'u"\xc3\xa5"', 'utf8'), globals), + unicode(b'\xc3\xa5', 'utf8')) self.assertRaises(TypeError, eval) self.assertRaises(TypeError, eval, ()) @@ -608,7 +608,7 @@ self.assertRaises(ValueError, float, " -0x3.p-1 ") if have_unicode: self.assertEqual(float(unicode(" 3.14 ")), 3.14) - self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14) + self.assertEqual(float(unicode(b" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14) # Implementation limitation in PyFloat_FromString() self.assertRaises(ValueError, float, unicode("1"*10000)) @@ -1673,7 +1673,7 @@ self.assertEqual(unichr(97), unicode('a')) self.assertEqual( unichr(sys.maxunicode), - unicode('\\U%08x' % (sys.maxunicode), 'unicode-escape') + unicode(('\\U%08x' % (sys.maxunicode)).encode("ascii"), 'unicode-escape') ) self.assertRaises(ValueError, unichr, sys.maxunicode+1) self.assertRaises(TypeError, unichr) Modified: python/branches/py3k-struni/Modules/posixmodule.c ============================================================================== --- python/branches/py3k-struni/Modules/posixmodule.c (original) +++ python/branches/py3k-struni/Modules/posixmodule.c Sat Apr 28 01:53:51 2007 @@ -6163,7 +6163,8 @@ static PyObject * posix_read(PyObject *self, PyObject *args) { - int fd, size, n; + int fd, size; + Py_ssize_t n; PyObject *buffer; if (!PyArg_ParseTuple(args, "ii:read", &fd, &size)) return NULL; @@ -6171,18 +6172,18 @@ errno = EINVAL; return posix_error(); } - buffer = PyString_FromStringAndSize((char *)NULL, size); + buffer = PyBytes_FromStringAndSize((char *)NULL, size); if (buffer == NULL) return NULL; Py_BEGIN_ALLOW_THREADS - n = read(fd, PyString_AsString(buffer), size); + n = read(fd, PyBytes_AsString(buffer), size); Py_END_ALLOW_THREADS if (n < 0) { Py_DECREF(buffer); return posix_error(); } if (n != size) - _PyString_Resize(&buffer, n); + PyBytes_Resize(buffer, n); return buffer; } @@ -8841,5 +8842,3 @@ #ifdef __cplusplus } #endif - - Modified: python/branches/py3k-struni/Objects/moduleobject.c ============================================================================== --- python/branches/py3k-struni/Objects/moduleobject.c (original) +++ python/branches/py3k-struni/Objects/moduleobject.c Sat Apr 28 01:53:51 2007 @@ -59,6 +59,7 @@ { PyObject *d; PyObject *nameobj; + char *s; if (!PyModule_Check(m)) { PyErr_BadArgument(); return NULL; @@ -66,11 +67,13 @@ d = ((PyModuleObject *)m)->md_dict; if (d == NULL || (nameobj = PyDict_GetItemString(d, "__name__")) == NULL || - !PyString_Check(nameobj)) + !(PyString_Check(nameobj) || PyUnicode_Check(nameobj))) { PyErr_SetString(PyExc_SystemError, "nameless module"); return NULL; } + if (PyUnicode_Check(nameobj)) + nameobj = _PyUnicode_AsDefaultEncodedString(nameobj, "replace"); return PyString_AsString(nameobj); } Modified: python/branches/py3k-struni/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k-struni/Objects/unicodeobject.c (original) +++ python/branches/py3k-struni/Objects/unicodeobject.c Sat Apr 28 01:53:51 2007 @@ -2072,7 +2072,6 @@ p = PyString_AS_STRING(repr); if (quotes) { - *p++ = 'u'; *p++ = (findchar(s, size, '\'') && !findchar(s, size, '"')) ? '"' : '\''; } @@ -2081,7 +2080,7 @@ /* Escape quotes and backslashes */ if ((quotes && - ch == (Py_UNICODE) PyString_AS_STRING(repr)[1]) || ch == '\\') { + ch == (Py_UNICODE) PyString_AS_STRING(repr)[0]) || ch == '\\') { *p++ = '\\'; *p++ = (char) ch; continue; @@ -2167,7 +2166,7 @@ *p++ = (char) ch; } if (quotes) - *p++ = PyString_AS_STRING(repr)[1]; + *p++ = PyString_AS_STRING(repr)[0]; *p = '\0'; _PyString_Resize(&repr, p - PyString_AS_STRING(repr)); Modified: python/branches/py3k-struni/Python/ast.c ============================================================================== --- python/branches/py3k-struni/Python/ast.c (original) +++ python/branches/py3k-struni/Python/ast.c Sat Apr 28 01:53:51 2007 @@ -3187,7 +3187,7 @@ } } #ifdef Py_USING_UNICODE - if (unicode || Py_UnicodeFlag) { + if (!*bytesmode) { return decode_unicode(s, len, rawmode, encoding); } #endif Modified: python/branches/py3k-struni/Python/bltinmodule.c ============================================================================== --- python/branches/py3k-struni/Python/bltinmodule.c (original) +++ python/branches/py3k-struni/Python/bltinmodule.c Sat Apr 28 01:53:51 2007 @@ -2270,7 +2270,7 @@ {"all", builtin_all, METH_O, all_doc}, {"any", builtin_any, METH_O, any_doc}, {"callable", builtin_callable, METH_O, callable_doc}, - {"chr", builtin_chr, METH_VARARGS, chr_doc}, + {"chr", builtin_unichr, METH_VARARGS, chr_doc}, {"cmp", builtin_cmp, METH_VARARGS, cmp_doc}, {"compile", (PyCFunction)builtin_compile, METH_VARARGS | METH_KEYWORDS, compile_doc}, {"delattr", builtin_delattr, METH_VARARGS, delattr_doc}, @@ -2375,7 +2375,7 @@ SETBUILTIN("set", &PySet_Type); SETBUILTIN("slice", &PySlice_Type); SETBUILTIN("staticmethod", &PyStaticMethod_Type); - SETBUILTIN("str", &PyString_Type); + SETBUILTIN("str", &PyUnicode_Type); SETBUILTIN("super", &PySuper_Type); SETBUILTIN("tuple", &PyTuple_Type); SETBUILTIN("type", &PyType_Type); Modified: python/branches/py3k-struni/Python/ceval.c ============================================================================== --- python/branches/py3k-struni/Python/ceval.c (original) +++ python/branches/py3k-struni/Python/ceval.c Sat Apr 28 01:53:51 2007 @@ -2633,7 +2633,7 @@ PyObject *keyword = kws[2*i]; PyObject *value = kws[2*i + 1]; int j; - if (keyword == NULL || !PyString_Check(keyword)) { + if (keyword == NULL || !(PyString_Check(keyword) || PyUnicode_Check(keyword))) { PyErr_Format(PyExc_TypeError, "%.200s() keywords must be strings", PyString_AsString(co->co_name)); Modified: python/branches/py3k-struni/Python/getargs.c ============================================================================== --- python/branches/py3k-struni/Python/getargs.c (original) +++ python/branches/py3k-struni/Python/getargs.c Sat Apr 28 01:53:51 2007 @@ -1081,7 +1081,7 @@ case 'S': { /* string object */ PyObject **p = va_arg(*p_va, PyObject **); - if (PyString_Check(arg)) + if (PyString_Check(arg) || PyUnicode_Check(arg)) *p = arg; else return converterr("string", arg, msgbuf, bufsize); @@ -1531,7 +1531,7 @@ while (PyDict_Next(keywords, &pos, &key, &value)) { int match = 0; char *ks; - if (!PyString_Check(key)) { + if (!PyString_Check(key) && !PyUnicode_Check(key)) { PyErr_SetString(PyExc_TypeError, "keywords must be strings"); return cleanreturn(0, freelist); Modified: python/branches/py3k-struni/Python/import.c ============================================================================== --- python/branches/py3k-struni/Python/import.c (original) +++ python/branches/py3k-struni/Python/import.c Sat Apr 28 01:53:51 2007 @@ -154,7 +154,7 @@ } } - if (Py_UnicodeFlag) { + { /* Fix the pyc_magic so that byte compiled code created using the all-Unicode method doesn't interfere with code created in normal operation mode. */ Modified: python/branches/py3k-struni/Python/pythonrun.c ============================================================================== --- python/branches/py3k-struni/Python/pythonrun.c (original) +++ python/branches/py3k-struni/Python/pythonrun.c Sat Apr 28 01:53:51 2007 @@ -76,7 +76,6 @@ int Py_NoSiteFlag; /* Suppress 'import site' */ int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */ int Py_FrozenFlag; /* Needed by getpath.c */ -int Py_UnicodeFlag = 0; /* Needed by compile.c */ int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */ /* Reference to 'warnings' module, to avoid importing it From python-checkins at python.org Sat Apr 28 02:36:50 2007 From: python-checkins at python.org (andrew.kuchling) Date: Sat, 28 Apr 2007 02:36:50 +0200 (CEST) Subject: [Python-checkins] r55014 - peps/trunk/pep-0008.txt peps/trunk/pep-0237.txt peps/trunk/pep-0242.txt peps/trunk/pep-0359.txt peps/trunk/pep-3118.txt Message-ID: <20070428003650.0211E1E4008@bag.python.org> Author: andrew.kuchling Date: Sat Apr 28 02:36:48 2007 New Revision: 55014 Modified: peps/trunk/pep-0008.txt peps/trunk/pep-0237.txt peps/trunk/pep-0242.txt peps/trunk/pep-0359.txt peps/trunk/pep-3118.txt Log: Fix 'the the' error Modified: peps/trunk/pep-0008.txt ============================================================================== --- peps/trunk/pep-0008.txt (original) +++ peps/trunk/pep-0008.txt Sat Apr 28 02:36:48 2007 @@ -502,7 +502,7 @@ only.) The conventions are about the same as those for functions. Modules that are designed for use via "from M import *" should use the - __all__ mechanism to prevent exporting globals, or use the the older + __all__ mechanism to prevent exporting globals, or use the older convention of prefixing such globals with an underscore (which you might want to do to indicate these globals are "module non-public"). Modified: peps/trunk/pep-0237.txt ============================================================================== --- peps/trunk/pep-0237.txt (original) +++ peps/trunk/pep-0237.txt Sat Apr 28 02:36:48 2007 @@ -276,7 +276,7 @@ import warnings warnings.filterwarnings("default", "", OverflowWarning) - See the python man page for the -W option and the the warnings + See the python man page for the -W option and the warnings module documentation for filterwarnings(). - If the OverflowWarning warning is turned into an error, Modified: peps/trunk/pep-0242.txt ============================================================================== --- peps/trunk/pep-0242.txt (original) +++ peps/trunk/pep-0242.txt Sat Apr 28 02:36:48 2007 @@ -51,7 +51,7 @@ long, and must support at least one kind of floating point number, equivalent to the present float. - The range and precision of the these required kinds are processor + The range and precision of these required kinds are processor dependent, as at present, except for the "long integer" kind, which can hold an arbitrary integer. Modified: peps/trunk/pep-0359.txt ============================================================================== --- peps/trunk/pep-0359.txt (original) +++ peps/trunk/pep-0359.txt Sat Apr 28 02:36:48 2007 @@ -159,7 +159,7 @@ hi_there.pack(side=Tkinter.LEFT) root.mainloop() -could be rewritten to group the the Button's function with its +could be rewritten to group the Button's function with its declaration:: root = Tkinter.Tk() Modified: peps/trunk/pep-3118.txt ============================================================================== --- peps/trunk/pep-3118.txt (original) +++ peps/trunk/pep-3118.txt Sat Apr 28 02:36:48 2007 @@ -947,7 +947,7 @@ /* Optional: if, after processing, we want to copy data from buffer back - into the the object + into the object we could do */ From buildbot at python.org Sat Apr 28 03:06:58 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 28 Apr 2007 01:06:58 +0000 Subject: [Python-checkins] buildbot warnings in alpha Debian 2.5 Message-ID: <20070428010658.6BA3B1E4008@bag.python.org> The Buildbot has detected a new failure of alpha Debian 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Debian%25202.5/builds/18 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch branches/release25-maint] HEAD Blamelist: brett.cannon,fred.drake,georg.brandl Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sat Apr 28 08:49:04 2007 From: python-checkins at python.org (brett.cannon) Date: Sat, 28 Apr 2007 08:49:04 +0200 (CEST) Subject: [Python-checkins] r55015 - peps/trunk/pep-0000.txt peps/trunk/pep-3122.txt Message-ID: <20070428064904.1810D1E4008@bag.python.org> Author: brett.cannon Date: Sat Apr 28 08:48:59 2007 New Revision: 55015 Added: peps/trunk/pep-3122.txt (contents, props changed) Modified: peps/trunk/pep-0000.txt Log: Add PEP 3122: Delineation of the main module. This PEP has already been rejected. Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Sat Apr 28 08:48:59 2007 @@ -259,6 +259,7 @@ SR 363 Syntax For Dynamic Attribute Access North SR 666 Reject Foolish Indentation Creighton SR 3103 A Switch/Case Statement GvR + SR 3122 Delineation of the main module Cannon Numerical Index @@ -478,6 +479,7 @@ S 3119 Introducing Abstract Base Classes GvR, Talin S 3120 Using UTF-8 as the default source encoding von L?wis S 3121 Module Initialization and finalization von L?wis + SR 3122 Delineation of the main module Cannon S 3141 A Type Hierarchy for Numbers Yasskin Added: peps/trunk/pep-3122.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-3122.txt Sat Apr 28 08:48:59 2007 @@ -0,0 +1,267 @@ +PEP: 3122 +Title: Delineation of the main module +Version: $Revision$ +Last-Modified: $Date$ +Author: Brett Cannon +Status: Rejected +Type: Standards Track +Content-Type: text/x-rst +Created: 27-Apr-2007 + +.. attention:: + This PEP has been rejected. Guido views running scripts within a + package as an anti-pattern [#guido-rejection]_. + +Abstract +======== + +Because of how name resolution works for relative imports in a world +where PEP 328 is implemented, the ability to execute modules within a +package ceases being possible. This failing stems from the fact that +the module being executed as the "main" module replaces its +``__name__`` attribute with ``"__main__"`` instead of leaving it as +the absolute name of the module. This breaks import's ability +to resolve relative imports from the main module into absolute names. + +In order to resolve this issue, this PEP proposes to change how the +main module is delineated. By leaving the ``__name__`` attribute in +a module alone and setting ``sys.main`` to the name of the main +module this will allow at least some instances of executing a module +within a package that uses relative imports. + +This PEP does not address the idea of introducing a module-level +function that is automatically executed like PEP 299 proposes. + + +The Problem +=========== + +With the introduction of PEP 328, relative imports became dependent on +the ``__name__`` attribute of the module performing the import. This +is because the use of dots in a relative import are used to strip away +parts of the calling module's name to calculate where in the package +hierarchy an import should fall (prior to PEP 328 relative +imports could fail and would fall back on absolute imports which had a +chance of succeeding). + +For instance, consider the import ``from .. import spam`` made from the +``bacon.ham.beans`` module (``bacon.ham.beans`` is not a package +itself, i.e., does not define ``__path__``). Name resolution of the +relative import takes the caller's name (``bacon.ham.beans``), splits +on dots, and then slices off the last n parts based on the level +(which is 2). In this example both ``ham`` and ``beans`` are dropped +and ``spam`` is joined with what is left (``bacon``). This leads to +the proper import of the module ``bacon.spam``. + +This reliance on the ``__name__`` attribute of a module when handling +relative imports becomes an issue when executing a script within a +package. Because the executing script has its name set to +``'__main__'``, import cannot resolve any relative imports, leading to +an ``ImportError``. + +For example, assume we have a package named ``bacon`` with an +``__init__.py`` file containing:: + + from . import spam + +Also create a module named ``spam`` within the ``bacon`` package (it +can be an empty file). Now if you try to execute the ``bacon`` +package (either through ``python bacon/__init__.py`` or +``python -m bacon``) you will get an ``ImportError`` about trying to +do a relative import from within a non-package. Obviously the import +is valid, but because of the setting of ``__name__`` to ``'__main__'`` +import thinks that ``bacon/__init__.py`` is not in a package since no +dots exist in ``__name__``. To see how the algorithm works in more +detail, see ``importlib.Import._resolve_name()`` in the sandbox +[#importlib]_. + +Currently a work-around is to remove all relative imports in the +module being executed and make them absolute. This is unfortunate, +though, as one should not be required to use a specific type of +resource in order to make a module in a package be able to be +executed. + + +The Solution +============ + +The solution to the problem is to not change the value of ``__name__`` +in modules. But there still needs to be a way to let executing code +know it is being executed as a script. This is handled with a new +attribute in the ``sys`` module named ``main``. + +When a module is being executed as a script, ``sys.main`` will be set +to the name of the module. This changes the current idiom of:: + + if __name__ == '__main__': + ... + +to:: + + import sys + if __name__ == sys.main: + ... + +The newly proposed solution does introduce an added line of +boilerplate which is a module import. But as the solution does not +introduce a new built-in or module attribute (as discussed in +`Rejected Ideas`_) it has been deemed worth the extra line. + +Another issue with the proposed solution (which also applies to all +rejected ideas as well) is that it does not directly solve the problem +of discovering the name of a file. Consider ``python bacon/spam.py``. +By the file name alone it is not obvious whether ``bacon`` is a +package. In order to properly find this out both the current +direction must exist on ``sys.path`` as well as ``bacon/__init__.py`` +existing. + +But this is the simple example. Consider ``python ../spam.py``. From +the file name alone it is not at all clear if ``spam.py`` is in a +package or not. One possible solution is to find out what the +absolute name of ``..``, check if a file named ``__init__.py`` exists, +and then look if the directory is on ``sys.path``. If it is not, then +continue to walk up the directory until no more ``__init__.py`` files +are found or the directory is found on ``sys.path``. + +This could potentially be an expensive process. If the package depth +happens to be deep then it could require a large amount of disk access +to discover where the package is anchored on ``sys.path``, if at all. +The stat calls alone can be expensive if the file system the executed +script is on is something like NFS. + +Because of these issues, only when the ``-m`` command-line argument +(introduced by PEP 338) is used will ``__name__`` be set. Otherwise +the fallback semantics of setting ``__name__`` to ``"__main__"`` will +occur. ``sys.main`` will still be set to the proper value, +regardless of what ``__name__`` is set to. + + +Implementation +============== + +When the ``-m`` option is used, ``sys.main`` will be set to the +argument passed in. ``sys.argv`` will be adjusted as it is currently. +Then the equivalent of ``__import__(self.main)`` will occur. This +differs from current semantics as the ``runpy`` module fetches the +code object for the file specified by the module name in order to +explicitly set ``__name__`` and other attributes. This is no longer +needed as import can perform its normal operation in this situation. + +If a file name is specified, then ``sys.main`` will be set to +``"__main__"``. The specified file will then be read and have a code +object created and then be executed with ``__name__`` set to +``"__main__"``. This mirrors current semantics. + + +Transition Plan +=============== + +In order for Python 2.6 to be able to support both the current +semantics and the proposed semantics, ``sys.main`` will always be set +to ``"__main__"``. Otherwise no change will occur for Python 2.6. +This unfortunately means that no benefit from this change will occur +in Python 2.6, but it maximizes compatibility for code that is to +work as much as possible with 2.6 and 3.0. + +To help transition to the new idiom, 2to3 [#2to3]_ will gain a rule to +transform the current ``if __name__ == '__main__': ...`` idiom to the +new one. This will not help with code that checks ``__name__`` +outside of the idiom, though. + + +Rejected Ideas +============== + +``__main__`` built-in +--------------------- + +A counter-proposal to introduce a built-in named ``__main__``. +The value of the built-in would be the name of the module being +executed (just like the proposed ``sys.main``). This would lead to a +new idiom of:: + + if __name__ == __main__: + ... + +A drawback is that the syntactic difference is subtle; the dropping +of quotes around "__main__". Some believe that for existing Python +programmers bugs will be introduced where the quotation marks will be +put on by accident. But one could argue that the bug would be +discovered quickly through testing as it is a very shallow bug. + +While the name of built-in could obviously be different (e.g., +``main``) the other drawback is that it introduces a new built-in. +With a simple solution such as ``sys.main`` being possible without +adding another built-in to Python, this proposal was rejected. + +``__main__`` module attribute +----------------------------- + +Another proposal was to add a ``__main__`` attribute to every module. +For the one that was executing as the main module, the attribute would +have a true value while all other modules had a false value. This has +a nice consequence of simplify the main module idiom to:: + + if __main__: + ... + +The drawback was the introduction of a new module attribute. It also +required more integration with the import machinery than the proposed +solution. + + +Use ``__file__`` instead of ``__name__`` +---------------------------------------- + +Any of the proposals could be changed to use the ``__file__`` +attribute on modules instead of ``__name__``, including the current +semantics. The problem with this is that with the proposed solutions +there is the issue of modules having no ``__file__`` attribute defined +or having the same value as other modules. + +The problem that comes up with the current semantics is you still have +to try to resolve the file path to a module name for the import to +work. + + +Special string subclass for ``__name__`` that overrides ``__eq__`` +------------------------------------------------------------------ + +One proposal was to define a subclass of ``str`` that overrode the +``__eq__`` method so that it would compare equal to ``"__main__"`` as +well as the actual name of the module. In all other respects the +subclass would be the same as ``str``. + +This was rejected as it seemed like too much of a hack. + + +References +========== + +.. [#2to3] 2to3 tool + (http://svn.python.org/view/sandbox/trunk/2to3/) [ViewVC] + +.. [#importlib] importlib + (http://svn.python.org/view/sandbox/trunk/import_in_py/importlib.py?view=markup) + [ViewVC] + +.. [#guido-rejection] Python-Dev email: "PEP to change how the main module is delineated" + (http://mail.python.org/pipermail/python-3000/2007-April/006793.html) + + + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: From buildbot at python.org Sat Apr 28 21:58:03 2007 From: buildbot at python.org (buildbot at python.org) Date: Sat, 28 Apr 2007 19:58:03 +0000 Subject: [Python-checkins] buildbot warnings in alpha Tru64 5.1 2.5 Message-ID: <20070428195803.B8BC11E4009@bag.python.org> The Buildbot has detected a new failure of alpha Tru64 5.1 2.5. Full details are available at: http://www.python.org/dev/buildbot/all/alpha%2520Tru64%25205.1%25202.5/builds/253 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: The web-page 'force build' button was pressed by 'nnorwitz': last compile failed, machine moved Build Source Stamp: [branch trunk] HEAD Blamelist: Build had warnings: warnings test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sun Apr 29 15:42:20 2007 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 29 Apr 2007 15:42:20 +0200 (CEST) Subject: [Python-checkins] r55016 - peps/trunk/pep-0000.txt peps/trunk/pep-3123.txt Message-ID: <20070429134220.D0C3A1E4009@bag.python.org> Author: martin.v.loewis Date: Sun Apr 29 15:42:17 2007 New Revision: 55016 Added: peps/trunk/pep-3123.txt (contents, props changed) Modified: peps/trunk/pep-0000.txt Log: Add PEP 3123. Modified: peps/trunk/pep-0000.txt ============================================================================== --- peps/trunk/pep-0000.txt (original) +++ peps/trunk/pep-0000.txt Sun Apr 29 15:42:17 2007 @@ -119,6 +119,7 @@ S 3119 Introducing Abstract Base Classes GvR, Talin S 3120 Using UTF-8 as the default source encoding von L?wis S 3121 Module Initialization and finalization von L?wis + S 3123 Making PyObject_HEAD conform to standard C von L?wis S 3141 A Type Hierarchy for Numbers Yasskin Finished PEPs (done, implemented in Subversion) @@ -480,6 +481,7 @@ S 3120 Using UTF-8 as the default source encoding von L?wis S 3121 Module Initialization and finalization von L?wis SR 3122 Delineation of the main module Cannon + S 3123 Making PyObject_HEAD conform to standard C von L?wis S 3141 A Type Hierarchy for Numbers Yasskin Added: peps/trunk/pep-3123.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-3123.txt Sun Apr 29 15:42:17 2007 @@ -0,0 +1,138 @@ +PEP: 3123 +Title: Making PyObject_HEAD conform to standard C +Version: $Revision$ +Last-Modified: $Date$ +Author: Martin v. L?wis +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 27-Apr-2007 +Python-Version: 3.0 +Post-History: + +Abstract +======== + +Python currently relies on undefined C behavior, with its +usage of PyObject_HEAD. This PEP proposes to change that +into standard C. + +Rationale +========= + +Standard C defines that an object must be accessed only through a +pointer of its type, and that all other accesses are undefined +behavior, with a few exceptions. In particular, the following +code has undefined behavior:: + + struct FooObject{ + PyObject_HEAD + int data; + }; + + PyObject *foo(struct FooObject*f){ + return (PyObject*)f; + } + + int bar(){ + struct FooObject *f = malloc(sizeof(struct FooObject)); + struct PyObject *o = foo(f); + f->ob_refcnt = 0; + o->ob_refcnt = 1; + return f->ob_refcnt; + } + +The problem here is that the storage is both accessed as +if it where struct PyObject, and as struct FooObject. + +Historically, compilers did not cause any problems with this +code. However, modern compiler use that clause as an +optimization opportunity, finding that f->ob_refcnt and +o->ob_refcnt cannot possibly refer to the same memory, and +that therefore the function should return 0, without having +to fetch the value of ob_refcnt at all in the return +statement. For GCC, Python now uses -fno-strict-aliasing +to work around that problem; with other compilers, it +may just see undefined behavior. Even with GCC, using +-fno-strict-aliasing may pessimize the generated code +unnecessarily. + +Specification +============= + +Standard C has one specific exception to its aliasing rules precisely +designed to support the case of Python: a value of a struct type may +also be accessed through a pointer to the first field. E.g. if a +struct starts with an int, the struct\* may also be cast to an int\*, +allowing to write int values into the first field. + +For Python, PyObject_HEAD and PyObject_VAR_HEAD will be changed +to not list all fields anymore, but list a single field of type +PyObject/PyVarObject:: + + typedef struct _object{ + _PyObject_HEAD_EXTRA + Py_ssize_t ob_refcnt; + struct _typeobject *ob_type; + }PyObject; + + typedef struct { + PyObject ob_base; + Py_ssize_t ob_size; + } PyVarObject; + + #define PyObject_HEAD PyObject ob_base; + #define PyObject_VAR_HEAD PyVarObject ob_base; + +Types defined as fixed-size structure will then include PyObject +as its first field; variable-sized objects PyVarObject. E.g.:: + + typedef struct{ + PyObject ob_base; + PyObject *start, *stop, *step; + } PySliceObject; + + typedef struct{ + PyVarObject ob_base; + PyObject **ob_item; + Py_ssize_t allocated; + } PyListObject; + +The above definitions of PyObject_HEAD is normative, so extension +authors MAY either use the macro, or put the ob_base field explicitly +into their structs. + +As a convention, the base field SHOULD be called ob_base. However, all +accesses to ob_refcnt and ob_type MUST cast the object pointer to +PyObject* (unless the pointer is already known to have that type), and +SHOULD use the respective accessor macros. To simplify access to +ob_type, a macro:: + + #define Py_Type(o) (((PyObject*)o)->ob_type) + +is added. + +Compatibility with Python 2.6 +============================= + +To support modules that compile with both Python 2.6 and Python 3.0, +the Py_Type macro is added to Python 2.6. The macros Py_INCREF +and Py_DECREF will be changed to cast their argument to PyObject\*, +so that module authors can also explicitly declare the ob_base +field in modules designed for Python 2.6. + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: From python-checkins at python.org Sun Apr 29 15:46:08 2007 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 29 Apr 2007 15:46:08 +0200 (CEST) Subject: [Python-checkins] r55017 - peps/trunk/pep-3123.txt Message-ID: <20070429134608.E012F1E4009@bag.python.org> Author: martin.v.loewis Date: Sun Apr 29 15:46:08 2007 New Revision: 55017 Modified: peps/trunk/pep-3123.txt Log: Add Brett's suggested changes. Modified: peps/trunk/pep-3123.txt ============================================================================== --- peps/trunk/pep-3123.txt (original) +++ peps/trunk/pep-3123.txt Sun Apr 29 15:46:08 2007 @@ -45,8 +45,8 @@ The problem here is that the storage is both accessed as if it where struct PyObject, and as struct FooObject. -Historically, compilers did not cause any problems with this -code. However, modern compiler use that clause as an +Historically, compilers did not have any problems with this +code. However, modern compilers use that clause as an optimization opportunity, finding that f->ob_refcnt and o->ob_refcnt cannot possibly refer to the same memory, and that therefore the function should return 0, without having @@ -110,7 +110,18 @@ #define Py_Type(o) (((PyObject*)o)->ob_type) -is added. +is added. E.g. the code blocks:: + + #define PyList_CheckExact(op) ((op)->ob_type == &PyList_Type) + + return func->ob_type->tp_name; + +needs to be changed to:: + + #define PyList_CheckExact(op) (Py_Type(op) == &PyList_Type) + + return Py_Type(func)->tp_name; + Compatibility with Python 2.6 ============================= From python-checkins at python.org Sun Apr 29 16:17:02 2007 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 29 Apr 2007 16:17:02 +0200 (CEST) Subject: [Python-checkins] r55018 - peps/trunk/pep-3121.txt Message-ID: <20070429141702.E8BC91E4009@bag.python.org> Author: martin.v.loewis Date: Sun Apr 29 16:17:02 2007 New Revision: 55018 Modified: peps/trunk/pep-3121.txt Log: Add edits suggested by Brett. Modified: peps/trunk/pep-3121.txt ============================================================================== --- peps/trunk/pep-3121.txt (original) +++ peps/trunk/pep-3121.txt Sun Apr 29 16:17:02 2007 @@ -19,8 +19,11 @@ multiple interpreters are not supported well. This PEP addresses these issues. +Problems +======== + Module Finalization -=================== +------------------- Currently, C modules are initialized usually once and then "live" forever. The only exception is when Py_Finalize() is called: then @@ -31,7 +34,7 @@ way to completely release all resources Python has allocated. Entry point name conflicts -========================== +-------------------------- The entry point is currently called init. This might conflict with other symbols also called init. In particular, @@ -40,7 +43,7 @@ _socket). Entry point signature -===================== +--------------------- The entry point is currently a procedure (returning void). This deviates from the usual calling conventions; callers can find out @@ -49,7 +52,7 @@ be the module created, or NULL in case of an exception. Multiple Interpreters -===================== +--------------------- Currently, extension modules share their state across all interpreters. This allows for undesirable information leakage across @@ -97,7 +100,7 @@ PyModuleDef*. The module state will be null-initialized. -Each module method with be passed the module object +Each module method will be passed the module object as the first parameter. To access the module data, a function:: From python-checkins at python.org Sun Apr 29 22:03:48 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 29 Apr 2007 22:03:48 +0200 (CEST) Subject: [Python-checkins] r55019 - peps/trunk/pep-3108.txt Message-ID: <20070429200348.870E11E4009@bag.python.org> Author: brett.cannon Date: Sun Apr 29 22:03:44 2007 New Revision: 55019 Modified: peps/trunk/pep-3108.txt Log: Add bsddb185 to the list of modules to go. Modified: peps/trunk/pep-3108.txt ============================================================================== --- peps/trunk/pep-3108.txt (original) +++ peps/trunk/pep-3108.txt Sun Apr 29 22:03:44 2007 @@ -267,6 +267,13 @@ + Turned off in Python 2.3. + Modules deemed unsafe. +* bsddb185 + + + Superceded by bsddb3 + + Not built by default. + + Documentation specifies that the "module should never be used + directly in new code". + * commands/popen2 + subprocess module replaces them [#pep-0324]_. From python-checkins at python.org Sun Apr 29 22:19:52 2007 From: python-checkins at python.org (brett.cannon) Date: Sun, 29 Apr 2007 22:19:52 +0200 (CEST) Subject: [Python-checkins] r55020 - peps/trunk/pep-0302.txt Message-ID: <20070429201952.937291E400C@bag.python.org> Author: brett.cannon Date: Sun Apr 29 22:19:50 2007 New Revision: 55020 Modified: peps/trunk/pep-0302.txt Log: Specify that load_module is to raise ImportError if an error has occurred and no exceptino is being propagated or it has been asked to load a module that it cannot. Also specify that __name__ must be set on all loaded modules. Modified: peps/trunk/pep-0302.txt ============================================================================== --- peps/trunk/pep-0302.txt (original) +++ peps/trunk/pep-0302.txt Sun Apr 29 22:19:50 2007 @@ -223,9 +223,13 @@ loader.load_module(fullname) - This method returns the loaded module. In many cases the importer - and loader can be one and the same object: importer.find_module() - would just return self. + This method returns the loaded module or raises and exception, + preferably ImportError if an existing exception is not being + propagated. If load_module() is asked to laod a module that it + cannot, ImportError is to be raised. + + In many cases the importer and loader can be one and the same + object: importer.find_module() would just return self. The 'fullname' argument of both methods is the fully qualified module name, for example "spam.eggs.ham". As explained above, when @@ -267,6 +271,9 @@ not having a __file__ attribute at all is reserved for built-in modules. + - The __name__ attribute must be set. If one uses + imp.new_module() then the attribute is set automatically. + - If it's a package, the __path__ variable must be set. This must be a list, but may be empty if __path__ has no further significance to the importer (more on this later). From python-checkins at python.org Mon Apr 30 01:53:27 2007 From: python-checkins at python.org (neal.norwitz) Date: Mon, 30 Apr 2007 01:53:27 +0200 (CEST) Subject: [Python-checkins] r55021 - python/trunk/Misc/build.sh Message-ID: <20070429235327.321791E4009@bag.python.org> Author: neal.norwitz Date: Mon Apr 30 01:53:24 2007 New Revision: 55021 Modified: python/trunk/Misc/build.sh Log: There really are some tests that are problematic. Modified: python/trunk/Misc/build.sh ============================================================================== --- python/trunk/Misc/build.sh (original) +++ python/trunk/Misc/build.sh Mon Apr 30 01:53:24 2007 @@ -67,7 +67,7 @@ # Note: test_XXX (none currently) really leak, but are disabled # so we don't send spam. Any test which really leaks should only # be listed here if there are also test cases under Lib/test/leakers. -LEAKY_TESTS="test_(XXX)" # Currently no tests should report spurious leaks. +LEAKY_TESTS="test_(cmd_line|socket)" # Skip these tests altogether when looking for leaks. These tests # do not need to be stored above in LEAKY_TESTS too. From python-checkins at python.org Mon Apr 30 01:56:23 2007 From: python-checkins at python.org (neal.norwitz) Date: Mon, 30 Apr 2007 01:56:23 +0200 (CEST) Subject: [Python-checkins] r55022 - python/branches/release25-maint/Misc/build.sh Message-ID: <20070429235623.A7EC91E4013@bag.python.org> Author: neal.norwitz Date: Mon Apr 30 01:56:19 2007 New Revision: 55022 Modified: python/branches/release25-maint/Misc/build.sh Log: Update with the version that has been running for a while. Most of the changes are to support multiple versions (ie, trunk and 2.5). Also check for conflicts in the .tex file when a release is cut. Modified: python/branches/release25-maint/Misc/build.sh ============================================================================== --- python/branches/release25-maint/Misc/build.sh (original) +++ python/branches/release25-maint/Misc/build.sh Mon Apr 30 01:56:19 2007 @@ -47,11 +47,12 @@ FAILURE_SUBJECT="Python Regression Test Failures" #FAILURE_MAILTO="YOUR_ACCOUNT at gmail.com" FAILURE_MAILTO="python-checkins at python.org" +#FAILURE_CC="optional--uncomment and set to desired address" REMOTE_SYSTEM="neal at dinsdale.python.org" -REMOTE_DIR="/data/ftp.python.org/pub/docs.python.org/dev/" +REMOTE_DIR="/data/ftp.python.org/pub/docs.python.org/dev/2.5" RESULT_FILE="$DIR/build/index.html" -INSTALL_DIR="/tmp/python-test/local" +INSTALL_DIR="/tmp/python-test-2.5/local" RSYNC_OPTS="-aC -e ssh" # Always run the installed version of Python. @@ -66,7 +67,7 @@ # Note: test_XXX (none currently) really leak, but are disabled # so we don't send spam. Any test which really leaks should only # be listed here if there are also test cases under Lib/test/leakers. -LEAKY_TESTS="test_(XXX)" # Currently no tests should report spurious leaks. +LEAKY_TESTS="test_(cmd_line|socket)" # Skip these tests altogether when looking for leaks. These tests # do not need to be stored above in LEAKY_TESTS too. @@ -76,7 +77,7 @@ LEAKY_SKIPS="-x test_compiler test_logging" # Change this flag to "yes" for old releases to only update/build the docs. -BUILD_DISABLED="no" +BUILD_DISABLED="yes" ## utility functions current_time() { @@ -91,7 +92,12 @@ mail_on_failure() { if [ "$NUM_FAILURES" != "0" ]; then - mutt -s "$FAILURE_SUBJECT $1 ($NUM_FAILURES)" $FAILURE_MAILTO < $2 + dest=$FAILURE_MAILTO + # FAILURE_CC is optional. + if [ "$FAILURE_CC" != "" ]; then + dest="$dest -c $FAILURE_CC" + fi + mutt -s "$FAILURE_SUBJECT $1 ($NUM_FAILURES)" $dest < $2 fi } @@ -208,8 +214,19 @@ cd $DIR/Doc F="make-doc.out" start=`current_time` -make >& ../build/$F -err=$? +# Doc/commontex/boilerplate.tex is expected to always have an outstanding +# modification for the date. When a release is cut, a conflict occurs. +# This allows us to detect this problem and not try to build the docs +# which will definitely fail with a conflict. +CONFLICTED_FILE=commontex/boilerplate.tex +conflict_count=`grep -c "<<<" $CONFLICTED_FILE` +if [ $conflict_count != 0 ]; then + echo "Conflict detected in $CONFLICTED_FILE. Doc build skipped." > ../build/$F + err=1 +else + make >& ../build/$F + err=$? +fi update_status "Making doc" "$F" $start if [ $err != 0 ]; then NUM_FAILURES=1 From python-checkins at python.org Mon Apr 30 02:55:39 2007 From: python-checkins at python.org (brett.cannon) Date: Mon, 30 Apr 2007 02:55:39 +0200 (CEST) Subject: [Python-checkins] r55023 - peps/trunk/pep-0328.txt peps/trunk/pep-3100.txt Message-ID: <20070430005539.B81AA1E4010@bag.python.org> Author: brett.cannon Date: Mon Apr 30 02:55:35 2007 New Revision: 55023 Modified: peps/trunk/pep-0328.txt peps/trunk/pep-3100.txt Log: Add mention that indirection entries in sys.modules will not be supported once absolute/relative imports are the only import semantics supported. Specifically mention that this will definitely happen for Python 3.0. Modified: peps/trunk/pep-0328.txt ============================================================================== --- peps/trunk/pep-0328.txt (original) +++ peps/trunk/pep-0328.txt Mon Apr 30 02:55:35 2007 @@ -278,6 +278,26 @@ system. +Relative Imports and Indirection Entries in sys.modules +======================================================= + +When packages were introduced, the concept of an indirection entry in +sys.modules came into existence [2]_. When an entry in sys.modules +for a module within a package had a value of None, it represented that +the module actually referenced the top-level module. For instance, +'Sound.Effects.string' might have a value of None in sys.modules. +That meant any import that resolved to that name actually was to +import the top-level 'string' module. + +This introduced an optimization for when a relative import was meant +to resolve to an absolute import. But since this PEP makes a very +clear delineation between absolute and relative imports, this +optimization is no longer needed. When absolute/relative imports +become the only import semantics available then indirection entries in +sys.modules will no longer be supported. + + + References ========== @@ -297,6 +317,8 @@ .. [1] http://mail.python.org/pipermail/python-dev/2004-March/043739.html +.. [2] http://www.python.org/doc/essays/packages.html + Copyright ========= Modified: peps/trunk/pep-3100.txt ============================================================================== --- peps/trunk/pep-3100.txt (original) +++ peps/trunk/pep-3100.txt Mon Apr 30 02:55:35 2007 @@ -83,8 +83,10 @@ where floats are inadvertantly accepted (PyArg_ParseTuple() i & l formats) * Remove from ... import * at function scope. This means that functions can always be optimized and support for unoptimized functions can go away. -* Imports will be absolute by default. [done] - Relative imports must be explicitly specified [#pep328]_ [done] +* Imports [#pep328]_ + + Imports will be absolute by default. [done] + + Relative imports must be explicitly specified. [done] + + Indirection entires in sys.modules will not be supported. * __init__.py might become optional in sub-packages. __init__.py will still be required for top-level packages. * Cleanup the Py_InitModule() variants {,3,4} (also import and parser APIs) From python-checkins at python.org Mon Apr 30 17:17:59 2007 From: python-checkins at python.org (kristjan.jonsson) Date: Mon, 30 Apr 2007 17:17:59 +0200 (CEST) Subject: [Python-checkins] r55024 - in python/trunk: Modules/datetimemodule.c Modules/getbuildinfo.c PC/make_versioninfo.c PCbuild8/PGInstrument.vsprops PCbuild8/PGUpdate.vsprops PCbuild8/Uninstal.wse PCbuild8/_bsddb PCbuild8/_bsddb.vcproj PCbuild8/_bsddb/_bsddb.vcproj PCbuild8/_ctypes PCbuild8/_ctypes.vcproj PCbuild8/_ctypes/_ctypes.vcproj PCbuild8/_ctypes_test PCbuild8/_ctypes_test.vcproj PCbuild8/_ctypes_test/_ctypes_test.vcproj PCbuild8/_elementtree PCbuild8/_elementtree.vcproj PCbuild8/_elementtree/_elementtree.vcproj PCbuild8/_msi PCbuild8/_msi.vcproj PCbuild8/_msi/_msi.vcproj PCbuild8/_socket PCbuild8/_socket.vcproj PCbuild8/_socket/_socket.vcproj PCbuild8/_sqlite3 PCbuild8/_sqlite3.vcproj PCbuild8/_sqlite3/_sqlite3.vcproj PCbuild8/_ssl.mak PCbuild8/_ssl.vcproj PCbuild8/_testcapi PCbuild8/_testcapi.vcproj PCbuild8/_testcapi/_testcapi.vcproj PCbuild8/_tkinter PCbuild8/_tkinter.vcproj PCbuild8/_tkinter/_tkinter.vcproj PCbuild8/build.bat PCbuild8/build_pgo.bat PCbuild8/build_ssl.py PCbuild8/bz2 PCbuild8/bz2.vcproj PCbuild8/bz2/bz2.vcproj PCbuild8/db.build PCbuild8/field3.py PCbuild8/make_buildinfo PCbuild8/make_buildinfo.c PCbuild8/make_buildinfo.vcproj PCbuild8/make_buildinfo/make_buildinfo.c PCbuild8/make_buildinfo/make_buildinfo.vcproj PCbuild8/make_versioninfo PCbuild8/make_versioninfo.vcproj PCbuild8/make_versioninfo/make_versioninfo.vcproj PCbuild8/pcbuild.sln PCbuild8/pyd.vsprops PCbuild8/pyd_d.vsprops PCbuild8/pyexpat PCbuild8/pyexpat.vcproj PCbuild8/pyexpat/pyexpat.vcproj PCbuild8/pyproject.vsprops PCbuild8/python PCbuild8/python.build PCbuild8/python.iss PCbuild8/python.vcproj PCbuild8/python/python.vcproj PCbuild8/python20.wse PCbuild8/pythoncore PCbuild8/pythoncore.vcproj PCbuild8/pythoncore/getbuildinfo.vsprops PCbuild8/pythoncore/pythoncore.vcproj PCbuild8/pythonw PCbuild8/pythonw.vcproj PCbuild8/pythonw/pythonw.vcproj PCbuild8/readme.txt PCbuild8/rmpyc.py PCbuild8/rt.bat PCbuild8/select PCbuild8/select.vcproj PCbuild8/select/select.vcproj PCbuild8/unicodedata PCbuild8/unicodedata.vcproj PCbuild8/unicodedata/unicodedata.vcproj PCbuild8/w9xpopen.vcproj PCbuild8/winsound PCbuild8/winsound.vcproj PCbuild8/winsound/winsound.vcproj Message-ID: <20070430151759.809F21E4016@bag.python.org> Author: kristjan.jonsson Date: Mon Apr 30 17:17:46 2007 New Revision: 55024 Added: python/trunk/PCbuild8/PGInstrument.vsprops python/trunk/PCbuild8/PGUpdate.vsprops python/trunk/PCbuild8/_bsddb/ python/trunk/PCbuild8/_bsddb/_bsddb.vcproj python/trunk/PCbuild8/_ctypes/ python/trunk/PCbuild8/_ctypes/_ctypes.vcproj python/trunk/PCbuild8/_ctypes_test/ python/trunk/PCbuild8/_ctypes_test/_ctypes_test.vcproj python/trunk/PCbuild8/_elementtree/ python/trunk/PCbuild8/_elementtree/_elementtree.vcproj python/trunk/PCbuild8/_msi/ python/trunk/PCbuild8/_msi/_msi.vcproj python/trunk/PCbuild8/_socket/ python/trunk/PCbuild8/_socket/_socket.vcproj python/trunk/PCbuild8/_sqlite3/ python/trunk/PCbuild8/_sqlite3/_sqlite3.vcproj python/trunk/PCbuild8/_testcapi/ python/trunk/PCbuild8/_testcapi/_testcapi.vcproj python/trunk/PCbuild8/_tkinter/ python/trunk/PCbuild8/_tkinter/_tkinter.vcproj python/trunk/PCbuild8/build.bat python/trunk/PCbuild8/build_pgo.bat python/trunk/PCbuild8/bz2/ python/trunk/PCbuild8/bz2/bz2.vcproj python/trunk/PCbuild8/make_buildinfo/ python/trunk/PCbuild8/make_buildinfo/make_buildinfo.c python/trunk/PCbuild8/make_buildinfo/make_buildinfo.vcproj python/trunk/PCbuild8/make_versioninfo/ python/trunk/PCbuild8/make_versioninfo/make_versioninfo.vcproj python/trunk/PCbuild8/pyd.vsprops python/trunk/PCbuild8/pyd_d.vsprops python/trunk/PCbuild8/pyexpat/ python/trunk/PCbuild8/pyexpat/pyexpat.vcproj python/trunk/PCbuild8/pyproject.vsprops python/trunk/PCbuild8/python/ python/trunk/PCbuild8/python/python.vcproj python/trunk/PCbuild8/pythoncore/ python/trunk/PCbuild8/pythoncore/getbuildinfo.vsprops python/trunk/PCbuild8/pythoncore/pythoncore.vcproj python/trunk/PCbuild8/pythonw/ python/trunk/PCbuild8/pythonw/pythonw.vcproj python/trunk/PCbuild8/select/ python/trunk/PCbuild8/select/select.vcproj python/trunk/PCbuild8/unicodedata/ python/trunk/PCbuild8/unicodedata/unicodedata.vcproj python/trunk/PCbuild8/winsound/ python/trunk/PCbuild8/winsound/winsound.vcproj Removed: python/trunk/PCbuild8/Uninstal.wse python/trunk/PCbuild8/_bsddb.vcproj python/trunk/PCbuild8/_ctypes.vcproj python/trunk/PCbuild8/_ctypes_test.vcproj python/trunk/PCbuild8/_elementtree.vcproj python/trunk/PCbuild8/_msi.vcproj python/trunk/PCbuild8/_socket.vcproj python/trunk/PCbuild8/_sqlite3.vcproj python/trunk/PCbuild8/_ssl.mak python/trunk/PCbuild8/_ssl.vcproj python/trunk/PCbuild8/_testcapi.vcproj python/trunk/PCbuild8/_tkinter.vcproj python/trunk/PCbuild8/build_ssl.py python/trunk/PCbuild8/bz2.vcproj python/trunk/PCbuild8/db.build python/trunk/PCbuild8/field3.py python/trunk/PCbuild8/make_buildinfo.c python/trunk/PCbuild8/make_buildinfo.vcproj python/trunk/PCbuild8/make_versioninfo.vcproj python/trunk/PCbuild8/pyexpat.vcproj python/trunk/PCbuild8/python.build python/trunk/PCbuild8/python.iss python/trunk/PCbuild8/python.vcproj python/trunk/PCbuild8/python20.wse python/trunk/PCbuild8/pythoncore.vcproj python/trunk/PCbuild8/pythonw.vcproj python/trunk/PCbuild8/select.vcproj python/trunk/PCbuild8/unicodedata.vcproj python/trunk/PCbuild8/w9xpopen.vcproj python/trunk/PCbuild8/winsound.vcproj Modified: python/trunk/Modules/datetimemodule.c python/trunk/Modules/getbuildinfo.c python/trunk/PC/make_versioninfo.c python/trunk/PCbuild8/pcbuild.sln python/trunk/PCbuild8/readme.txt python/trunk/PCbuild8/rmpyc.py python/trunk/PCbuild8/rt.bat Log: Complete revamp of PCBuild8 directory. Use subdirectories for each project under the main pcbuild solution. Now make extensive use of property sheets to simplify project configuration. x64 build fully supported, and the process for building PGO version (Profiler Guided Optimization) simplified. All projects are now present, except _ssl, which needs to be reimplemented. Also, some of the projects that require external libraries need extra work to fully compile on x64. Modified: python/trunk/Modules/datetimemodule.c ============================================================================== --- python/trunk/Modules/datetimemodule.c (original) +++ python/trunk/Modules/datetimemodule.c Mon Apr 30 17:17:46 2007 @@ -13,7 +13,9 @@ /* Differentiate between building the core module and building extension * modules. */ +#ifndef Py_BUILD_CORE #define Py_BUILD_CORE +#endif #include "datetime.h" #undef Py_BUILD_CORE Modified: python/trunk/Modules/getbuildinfo.c ============================================================================== --- python/trunk/Modules/getbuildinfo.c (original) +++ python/trunk/Modules/getbuildinfo.c Mon Apr 30 17:17:46 2007 @@ -20,10 +20,7 @@ #endif #endif -#ifdef SUBWCREV #define SVNVERSION "$WCRANGE$$WCMODS?M:$" -#endif - const char * Py_GetBuildInfo(void) { @@ -40,9 +37,9 @@ const char * _Py_svnversion(void) { -#ifdef SVNVERSION - return SVNVERSION; -#else + /* the following string can be modified by subwcrev.exe */ + static const char svnversion[] = SVNVERSION; + if (!strstr(svnversion, "$")) + return svnversion; /* it was interpolated */ return "exported"; -#endif } Modified: python/trunk/PC/make_versioninfo.c ============================================================================== --- python/trunk/PC/make_versioninfo.c (original) +++ python/trunk/PC/make_versioninfo.c Mon Apr 30 17:17:46 2007 @@ -27,7 +27,12 @@ PY_MICRO_VERSION*1000 + PY_RELEASE_LEVEL*10 + PY_RELEASE_SERIAL); printf("#define MS_DLL_ID \"%d.%d\"\n", PY_MAJOR_VERSION, PY_MINOR_VERSION); + printf("#ifndef _DEBUG\n"); printf("#define PYTHON_DLL_NAME \"python%d%d.dll\"\n", PY_MAJOR_VERSION, PY_MINOR_VERSION); + printf("#else\n"); + printf("#define PYTHON_DLL_NAME \"python%d%d_d.dll\"\n", + PY_MAJOR_VERSION, PY_MINOR_VERSION); + printf("#endif\n"); return 0; } Added: python/trunk/PCbuild8/PGInstrument.vsprops ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/PGInstrument.vsprops Mon Apr 30 17:17:46 2007 @@ -0,0 +1,13 @@ + + + + Added: python/trunk/PCbuild8/PGUpdate.vsprops ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/PGUpdate.vsprops Mon Apr 30 17:17:46 2007 @@ -0,0 +1,12 @@ + + + + Deleted: /python/trunk/PCbuild8/Uninstal.wse ============================================================================== --- /python/trunk/PCbuild8/Uninstal.wse Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,514 +0,0 @@ -Document Type: WSE -item: Global - Version=8.14 - Flags=00000100 - Split=1420 - Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - Copy Default=1 - Japanese Font Name=MS Gothic - Japanese Font Size=10 - Start Gradient=0 0 255 - End Gradient=0 0 0 - Windows Flags=00000000000000000000101000001000 - Message Font=MS Sans Serif - Font Size=8 - Disk Label=GLBS - Disk Filename=INSTALL - Patch Flags=0000000000000001 - Patch Threshold=200 - Patch Memory=4096 - Per-User Version ID=1 - Crystal Format=10111100101100000010001001001001 - Step View=&Properties -end -item: Remark - Text=Note from Tim: This is a verbatim copy of Wise's Uninstal.wse, altered at the end to write -end -item: Remark - Text=uninstall info under HKCU instead of HKLM if our DOADMIN var is false. -end -item: Remark -end -item: Remark - Text= Install Support for uninstalling the application. -end -item: Remark -end -item: Set Variable - Variable=UNINSTALL_PATH - Value=%_LOGFILE_PATH_% - Flags=00000010 -end -item: Set Variable - Variable=UNINSTALL_PATH - Value=%UNINSTALL_PATH%\UNWISE.EXE -end -item: Compiler Variable If - Variable=_EXE_OS_TYPE_ - Value=WIN32 -end -item: Install File - Source=%_WISE_%\UNWISE32.EXE - Destination=%UNINSTALL_PATH% - Flags=0000000000000010 -end -item: Compiler Variable Else -end -item: Install File - Source=%_WISE_%\UNWISE.EXE - Destination=%UNINSTALL_PATH% - Flags=0000000000000010 -end -item: Compiler Variable End -end -item: Remark -end -item: Remark - Text= Install Support for multiple languages -end -item: Remark -end -item: Set Variable - Variable=UNINSTALL_LANG - Value=%UNINSTALL_PATH% - Flags=00000010 -end -item: Set Variable - Variable=UNINSTALL_LANG - Value=%UNINSTALL_LANG%\UNWISE.INI -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=C - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.FRA - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_C_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.FRA - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=D - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.FRA - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_D_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.FRA - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=E - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.DEU - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_E_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.DEU - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=F - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.PTG - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_F_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.PTG - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=G - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.ESP - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_G_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.ESP - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=H - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.ESP - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_H_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.ESP - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=I - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.ITA - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_I_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.ITA - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=J - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.DAN - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_J_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.DAN - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=K - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.FIN - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_K_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.FIN - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=L - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.ISL - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_L_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.ISL - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=M - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.NLD - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_M_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.NLD - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=N - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.NOR - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_N_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.NOR - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=O - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.SVE - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_O_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.SVE - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Compiler Variable If - Variable=_LANG_LIST_ - Value=P - Flags=00000010 -end -item: Compiler Variable If - Value=%_WISE_%\LANGUAGE\UNWISE.JPN - Flags=00000011 -end -item: If/While Statement - Variable=LANG - Value=%_LANG_P_NAME_% -end -item: Install File - Source=%_WISE_%\LANGUAGE\UNWISE.JPN - Destination=%UNINSTALL_LANG% - Flags=0000000000000010 -end -item: End Block -end -item: Compiler Variable End -end -item: Compiler Variable End -end -item: Remark -end -item: Remark - Text= Install the add/remove or uninstall icon -end -item: Remark -end -item: Set Variable - Variable=UNINSTALL_PATH - Value=%UNINSTALL_PATH% - Flags=00010100 -end -item: Set Variable - Variable=INST_LOG_PATH - Value=%_LOGFILE_PATH_% - Flags=00010100 -end -item: Check Configuration - Flags=10111011 -end -item: If/While Statement - Variable=DOADMIN - Value=1 -end -item: Remark - Text=Write uninstall info under HKLM. This if/else/end block added by Tim. -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%APPTITLE% - Value Name=DisplayName - Root=2 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%UNINSTALL_PATH% %INST_LOG_PATH% - New Value= - Value Name=UninstallString - Root=2 -end -item: Else Statement -end -item: Remark - Text=The same, but write under HKCU instead. -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%APPTITLE% - Value Name=DisplayName - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%UNINSTALL_PATH% %INST_LOG_PATH% - New Value= - Value Name=UninstallString - Root=1 -end -item: End Block -end -item: Else Statement -end -item: Add ProgMan Icon - Group=%GROUP% - Icon Name=Uninstall %APPTITLE% - Command Line=%UNINSTALL_PATH% %INST_LOG_PATH% -end -item: End Block -end -item: Check Configuration - Flags=11110010 -end -item: If/While Statement - Variable=DOBRAND - Value=1 -end -item: Edit Registry - Total Keys=2 - item: Key - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%COMPANY% - Value Name=RegCompany - Root=2 - end - item: Key - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%NAME% - Value Name=RegOwner - Root=2 - end -end -item: End Block -end -item: End Block -end Deleted: /python/trunk/PCbuild8/_bsddb.vcproj ============================================================================== --- /python/trunk/PCbuild8/_bsddb.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,385 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/_bsddb/_bsddb.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/_bsddb/_bsddb.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,652 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/_ctypes.vcproj ============================================================================== --- /python/trunk/PCbuild8/_ctypes.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,410 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/_ctypes/_ctypes.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/_ctypes/_ctypes.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,765 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/_ctypes_test.vcproj ============================================================================== --- /python/trunk/PCbuild8/_ctypes_test.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,370 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/_ctypes_test/_ctypes_test.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/_ctypes_test/_ctypes_test.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,640 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/_elementtree.vcproj ============================================================================== --- /python/trunk/PCbuild8/_elementtree.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,388 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/_elementtree/_elementtree.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/_elementtree/_elementtree.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,724 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/_msi.vcproj ============================================================================== --- /python/trunk/PCbuild8/_msi.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,375 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/_msi/_msi.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/_msi/_msi.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,644 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/_socket.vcproj ============================================================================== --- /python/trunk/PCbuild8/_socket.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,381 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/_socket/_socket.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/_socket/_socket.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,648 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/_sqlite3.vcproj ============================================================================== --- /python/trunk/PCbuild8/_sqlite3.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,411 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/_sqlite3/_sqlite3.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/_sqlite3/_sqlite3.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,724 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/_ssl.mak ============================================================================== --- /python/trunk/PCbuild8/_ssl.mak Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,21 +0,0 @@ - -!IFDEF DEBUG -MODULE=_ssl_d.pyd -TEMP_DIR=x86-temp-debug/_ssl -CFLAGS=/Od /Zi /MDd /LDd /DDEBUG /D_DEBUG /DWIN32 -SSL_LIB_DIR=$(SSL_DIR)/out32.dbg -!ELSE -MODULE=_ssl.pyd -TEMP_DIR=x86-temp-release/_ssl -CFLAGS=/Ox /MD /LD /DWIN32 -SSL_LIB_DIR=$(SSL_DIR)/out32 -!ENDIF - -INCLUDES=-I ../Include -I ../PC -I $(SSL_DIR)/inc32 -LIBS=gdi32.lib wsock32.lib user32.lib advapi32.lib /libpath:$(SSL_LIB_DIR) libeay32.lib ssleay32.lib - -SOURCE=../Modules/_ssl.c $(SSL_LIB_DIR)/libeay32.lib $(SSL_LIB_DIR)/ssleay32.lib - -$(MODULE): $(SOURCE) ../PC/*.h ../Include/*.h - @if not exist "$(TEMP_DIR)/." mkdir "$(TEMP_DIR)" - cl /nologo $(SOURCE) $(CFLAGS) /Fo$(TEMP_DIR)\$*.obj $(INCLUDES) /link /out:$(MODULE) $(LIBS) Deleted: /python/trunk/PCbuild8/_ssl.vcproj ============================================================================== --- /python/trunk/PCbuild8/_ssl.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Deleted: /python/trunk/PCbuild8/_testcapi.vcproj ============================================================================== --- /python/trunk/PCbuild8/_testcapi.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,374 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/_testcapi/_testcapi.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/_testcapi/_testcapi.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,636 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/_tkinter.vcproj ============================================================================== --- /python/trunk/PCbuild8/_tkinter.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/_tkinter/_tkinter.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/_tkinter/_tkinter.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,640 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: python/trunk/PCbuild8/build.bat ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/build.bat Mon Apr 30 17:17:46 2007 @@ -0,0 +1,17 @@ + at echo off +rem A batch program to build or rebuild a particular configuration. +rem just for convenience. + +setlocal +set platf=Win32 +set conf=Release +set build=/build + +:CheckOpts +if "%1"=="-c" (set conf=%2) & shift & shift & goto CheckOpts +if "%1"=="-p" (set platf=%2) & shift & shift & goto CheckOpts +if "%1"=="-r" (set build=/rebuild) & shift & goto CheckOpts + +set cmd=devenv pcbuild.sln %build% "%conf%|%platf%" +echo %cmd% +%cmd% \ No newline at end of file Added: python/trunk/PCbuild8/build_pgo.bat ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/build_pgo.bat Mon Apr 30 17:17:46 2007 @@ -0,0 +1,39 @@ + at echo off +rem A batch program to build PGO (Profile guided optimization) by first +rem building instrumented binaries, then running the testsuite, and +rem finally building the optimized code. +rem Note, after the first instrumented run, one can just keep on +rem building the PGUpdate configuration while developing. + +setlocal +set platf=Win32 + +rem use the performance testsuite. This is quick and simple +set job1=..\tools\pybench\pybench.py -n 1 -C 1 --with-gc +set path1=..\tools\pybench + +rem or the whole testsuite for more thorough testing +set job2=..\lib\test\regrtest.py +set path2=..\lib + +set job=%job1% +set clrpath=%path1% + +:CheckOpts +if "%1"=="-p" (set platf=%2) & shift & shift & goto CheckOpts +if "%1"=="-2" (set job=%job2%) & (set clrpath=%path2%) & shift & goto CheckOpts + +set folder=%platf%PGO + + + at echo on +rem build the instrumented version +call build -r -p %platf% -c PGInstrument + +rem remove .pyc files, .pgc files and execute the job +%folder%\python.exe rmpyc.py %clrpath% +del %folder%\*.pgc +%folder%\python.exe %job% + +rem finally build the optimized version +call build -r -p %platf% -c PGUpdate Deleted: /python/trunk/PCbuild8/build_ssl.py ============================================================================== --- /python/trunk/PCbuild8/build_ssl.py Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,163 +0,0 @@ -# Script for building the _ssl module for Windows. -# Uses Perl to setup the OpenSSL environment correctly -# and build OpenSSL, then invokes a simple nmake session -# for _ssl.pyd itself. - -# THEORETICALLY, you can: -# * Unpack the latest SSL release one level above your main Python source -# directory. It is likely you will already find the zlib library and -# any other external packages there. -# * Install ActivePerl and ensure it is somewhere on your path. -# * Run this script from the PCBuild directory. -# -# it should configure and build SSL, then build the ssl Python extension -# without intervention. - -import os, sys, re - -# Find all "foo.exe" files on the PATH. -def find_all_on_path(filename, extras = None): - entries = os.environ["PATH"].split(os.pathsep) - ret = [] - for p in entries: - fname = os.path.abspath(os.path.join(p, filename)) - if os.path.isfile(fname) and fname not in ret: - ret.append(fname) - if extras: - for p in extras: - fname = os.path.abspath(os.path.join(p, filename)) - if os.path.isfile(fname) and fname not in ret: - ret.append(fname) - return ret - -# Find a suitable Perl installation for OpenSSL. -# cygwin perl does *not* work. ActivePerl does. -# Being a Perl dummy, the simplest way I can check is if the "Win32" package -# is available. -def find_working_perl(perls): - for perl in perls: - fh = os.popen(perl + ' -e "use Win32;"') - fh.read() - rc = fh.close() - if rc: - continue - return perl - print "Can not find a suitable PERL:" - if perls: - print " the following perl interpreters were found:" - for p in perls: - print " ", p - print " None of these versions appear suitable for building OpenSSL" - else: - print " NO perl interpreters were found on this machine at all!" - print " Please install ActivePerl and ensure it appears on your path" - print "The Python SSL module was not built" - return None - -# Locate the best SSL directory given a few roots to look into. -def find_best_ssl_dir(sources): - candidates = [] - for s in sources: - try: - s = os.path.abspath(s) - fnames = os.listdir(s) - except os.error: - fnames = [] - for fname in fnames: - fqn = os.path.join(s, fname) - if os.path.isdir(fqn) and fname.startswith("openssl-"): - candidates.append(fqn) - # Now we have all the candidates, locate the best. - best_parts = [] - best_name = None - for c in candidates: - parts = re.split("[.-]", os.path.basename(c))[1:] - # eg - openssl-0.9.7-beta1 - ignore all "beta" or any other qualifiers - if len(parts) >= 4: - continue - if parts > best_parts: - best_parts = parts - best_name = c - if best_name is not None: - print "Found an SSL directory at '%s'" % (best_name,) - else: - print "Could not find an SSL directory in '%s'" % (sources,) - return best_name - -def main(): - debug = "-d" in sys.argv - build_all = "-a" in sys.argv - make_flags = "" - if build_all: - make_flags = "-a" - # perl should be on the path, but we also look in "\perl" and "c:\\perl" - # as "well known" locations - perls = find_all_on_path("perl.exe", ["\\perl\\bin", "C:\\perl\\bin"]) - perl = find_working_perl(perls) - if perl is None: - sys.exit(1) - - print "Found a working perl at '%s'" % (perl,) - # Look for SSL 2 levels up from pcbuild - ie, same place zlib etc all live. - ssl_dir = find_best_ssl_dir(("../..",)) - if ssl_dir is None: - sys.exit(1) - - old_cd = os.getcwd() - try: - os.chdir(ssl_dir) - # If the ssl makefiles do not exist, we invoke Perl to generate them. - if not os.path.isfile(os.path.join(ssl_dir, "32.mak")) or \ - not os.path.isfile(os.path.join(ssl_dir, "d32.mak")): - print "Creating the makefiles..." - # Put our working Perl at the front of our path - os.environ["PATH"] = os.path.split(perl)[0] + \ - os.pathsep + \ - os.environ["PATH"] - # ms\32all.bat will reconfigure OpenSSL and then try to build - # all outputs (debug/nondebug/dll/lib). So we filter the file - # to exclude any "nmake" commands and then execute. - tempname = "ms\\32all_py.bat" - - in_bat = open("ms\\32all.bat") - temp_bat = open(tempname,"w") - while 1: - cmd = in_bat.readline() - print 'cmd', repr(cmd) - if not cmd: break - if cmd.strip()[:5].lower() == "nmake": - continue - temp_bat.write(cmd) - in_bat.close() - temp_bat.close() - os.system(tempname) - try: - os.remove(tempname) - except: - pass - - # Now run make. - print "Executing nmake over the ssl makefiles..." - if debug: - rc = os.system("nmake /nologo -f d32.mak") - if rc: - print "Executing d32.mak failed" - print rc - sys.exit(rc) - else: - rc = os.system("nmake /nologo -f 32.mak") - if rc: - print "Executing 32.mak failed" - print rc - sys.exit(rc) - finally: - os.chdir(old_cd) - # And finally, we can build the _ssl module itself for Python. - defs = "SSL_DIR=%s" % (ssl_dir,) - if debug: - defs = defs + " " + "DEBUG=1" - rc = os.system('nmake /nologo -f _ssl.mak ' + defs + " " + make_flags) - sys.exit(rc) - -if __name__=='__main__': - main() Deleted: /python/trunk/PCbuild8/bz2.vcproj ============================================================================== --- /python/trunk/PCbuild8/bz2.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,390 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/bz2/bz2.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/bz2/bz2.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,652 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/db.build ============================================================================== --- /python/trunk/PCbuild8/db.build Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,10 +0,0 @@ - - - - - - - - - - Deleted: /python/trunk/PCbuild8/field3.py ============================================================================== --- /python/trunk/PCbuild8/field3.py Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,35 +0,0 @@ -# An absurd workaround for the lack of arithmetic in MS's resource compiler. -# After building Python, run this, then paste the output into the appropriate -# part of PC\python_nt.rc. -# Example output: -# -# * For 2.3a0, -# * PY_MICRO_VERSION = 0 -# * PY_RELEASE_LEVEL = 'alpha' = 0xA -# * PY_RELEASE_SERIAL = 1 -# * -# * and 0*1000 + 10*10 + 1 = 101. -# */ -# #define FIELD3 101 - -import sys - -major, minor, micro, level, serial = sys.version_info -levelnum = {'alpha': 0xA, - 'beta': 0xB, - 'candidate': 0xC, - 'final': 0xF, - }[level] -string = sys.version.split()[0] # like '2.3a0' - -print " * For %s," % string -print " * PY_MICRO_VERSION = %d" % micro -print " * PY_RELEASE_LEVEL = %r = %s" % (level, hex(levelnum)) -print " * PY_RELEASE_SERIAL = %d" % serial -print " *" - -field3 = micro * 1000 + levelnum * 10 + serial - -print " * and %d*1000 + %d*10 + %d = %d" % (micro, levelnum, serial, field3) -print " */" -print "#define FIELD3", field3 Deleted: /python/trunk/PCbuild8/make_buildinfo.c ============================================================================== --- /python/trunk/PCbuild8/make_buildinfo.c Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,81 +0,0 @@ -#include -#include -#include -#include - -/* This file creates the getbuildinfo2.c file, by - invoking subwcrev.exe (if found). - If this isn't a subversion checkout, or subwcrev isn't - found, it copies ..\\Modules\\getbuildinfo.c instead. - - A file, getbuildinfo2.h is then updated to define - SUBWCREV if it was a subversion checkout. - - getbuildinfo2.c is part of the pythoncore project with - getbuildinfo2.h as a forced include. This helps - VisualStudio refrain from unnecessary compiles much of the - time. - - Currently, subwcrev.exe is found from the registry entries - of TortoiseSVN. - - make_buildinfo.exe is called as a pre-build step for pythoncore. - -*/ - -int make_buildinfo2() -{ - struct _stat st; - HKEY hTortoise; - char command[500]; - DWORD type, size; - if (_stat(".svn", &st) < 0) - return 0; - /* Allow suppression of subwcrev.exe invocation if a no_subwcrev file is present. */ - if (_stat("no_subwcrev", &st) == 0) - return 0; - if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\TortoiseSVN", &hTortoise) != ERROR_SUCCESS && - RegOpenKey(HKEY_CURRENT_USER, "Software\\TortoiseSVN", &hTortoise) != ERROR_SUCCESS) - /* Tortoise not installed */ - return 0; - command[0] = '"'; /* quote the path to the executable */ - size = sizeof(command) - 1; - if (RegQueryValueEx(hTortoise, "Directory", 0, &type, command+1, &size) != ERROR_SUCCESS || - type != REG_SZ) - /* Registry corrupted */ - return 0; - strcat_s(command, sizeof(command), "bin\\subwcrev.exe"); - if (_stat(command+1, &st) < 0) - /* subwcrev.exe not part of the release */ - return 0; - strcat_s(command, sizeof(command), "\" .. ..\\Modules\\getbuildinfo.c getbuildinfo2.c"); - puts(command); fflush(stdout); - if (system(command) < 0) - return 0; - return 1; -} - -int main(int argc, char*argv[]) -{ - char command[500] = ""; - int svn; - FILE *f; - - if (fopen_s(&f, "getbuildinfo2.h", "w")) - return EXIT_FAILURE; - /* Get getbuildinfo.c from svn as getbuildinfo2.c */ - svn = make_buildinfo2(); - if (svn) { - puts("got getbuildinfo2.c from svn. Updating getbuildinfo2.h"); - /* yes. make sure SUBWCREV is defined */ - fprintf(f, "#define SUBWCREV\n"); - } else { - puts("didn't get getbuildinfo2.c from svn. Copying from Modules and clearing getbuildinfo2.h"); - strcat_s(command, sizeof(command), "copy ..\\Modules\\getbuildinfo.c getbuildinfo2.c"); - puts(command); fflush(stdout); - if (system(command) < 0) - return EXIT_FAILURE; - } - fclose(f); - return 0; -} \ No newline at end of file Deleted: /python/trunk/PCbuild8/make_buildinfo.vcproj ============================================================================== --- /python/trunk/PCbuild8/make_buildinfo.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/make_buildinfo/make_buildinfo.c ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/make_buildinfo/make_buildinfo.c Mon Apr 30 17:17:46 2007 @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +/* This file creates the local getbuildinfo.c file, by + invoking subwcrev.exe (if found). This replaces tokens + int the file with information about the build. + If this isn't a subversion checkout, or subwcrev isn't + found, it copies ..\\Modules\\getbuildinfo.c instead. + + Currently, subwcrev.exe is found from the registry entries + of TortoiseSVN. + + make_buildinfo.exe is called as a pre-build step for pythoncore. +*/ + +int make_buildinfo2() +{ + struct _stat st; + HKEY hTortoise; + char command[500]; + DWORD type, size; + if (_stat("..\\.svn", &st) < 0) + return 0; + /* Allow suppression of subwcrev.exe invocation if a no_subwcrev file is present. */ + if (_stat("no_subwcrev", &st) == 0) + return 0; + if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\TortoiseSVN", &hTortoise) != ERROR_SUCCESS && + RegOpenKey(HKEY_CURRENT_USER, "Software\\TortoiseSVN", &hTortoise) != ERROR_SUCCESS) + /* Tortoise not installed */ + return 0; + command[0] = '"'; /* quote the path to the executable */ + size = sizeof(command) - 1; + if (RegQueryValueEx(hTortoise, "Directory", 0, &type, command+1, &size) != ERROR_SUCCESS || + type != REG_SZ) + /* Registry corrupted */ + return 0; + strcat_s(command, sizeof(command), "bin\\subwcrev.exe"); + if (_stat(command+1, &st) < 0) + /* subwcrev.exe not part of the release */ + return 0; + strcat_s(command, sizeof(command), "\" .. ..\\Modules\\getbuildinfo.c getbuildinfo.c"); + puts(command); fflush(stdout); + if (system(command) < 0) + return 0; + return 1; +} + +int main(int argc, char*argv[]) +{ + char command[500] = ""; + int svn; + /* Get getbuildinfo.c from svn as getbuildinfo2.c */ + svn = make_buildinfo2(); + if (svn) { + puts("subcwrev succeeded, generated getbuildinfo.c"); + } else { + puts("Couldn't run subwcrev.exe on getbuildinfo.c. Copying it"); + strcat_s(command, sizeof(command), "copy /Y ..\\Modules\\getbuildinfo.c getbuildinfo.c"); + puts(command); fflush(stdout); + if (system(command) < 0) + return EXIT_FAILURE; + } + return 0; +} \ No newline at end of file Added: python/trunk/PCbuild8/make_buildinfo/make_buildinfo.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/make_buildinfo/make_buildinfo.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/make_versioninfo.vcproj ============================================================================== --- /python/trunk/PCbuild8/make_versioninfo.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,204 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/make_versioninfo/make_versioninfo.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/make_versioninfo/make_versioninfo.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modified: python/trunk/PCbuild8/pcbuild.sln ============================================================================== --- python/trunk/PCbuild8/pcbuild.sln (original) +++ python/trunk/PCbuild8/pcbuild.sln Mon Apr 30 17:17:46 2007 @@ -1,304 +1,410 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythoncore", "pythoncore.vcproj", "{CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythoncore", "pythoncore\pythoncore.vcproj", "{987306EC-6BAD-4440-B4FB-A699A1EE6A28}" ProjectSection(ProjectDependencies) = postProject - {F0E0541E-F17D-430B-97C4-93ADF0DD284E} = {F0E0541E-F17D-430B-97C4-93ADF0DD284E} - {C73F0EC1-358B-4177-940F-0846AC8B04CD} = {C73F0EC1-358B-4177-940F-0846AC8B04CD} + {87AB87DB-B665-4621-A67B-878C15B93FF0} = {87AB87DB-B665-4621-A67B-878C15B93FF0} + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED} = {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythonw", "pythonw.vcproj", "{F4229CC3-873C-49AE-9729-DD308ED4CD4A}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_versioninfo", "make_versioninfo\make_versioninfo.vcproj", "{2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_buildinfo", "make_buildinfo\make_buildinfo.vcproj", "{87AB87DB-B665-4621-A67B-878C15B93FF0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes", "_ctypes\_ctypes.vcproj", "{8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}" ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "select", "select.vcproj", "{97239A56-DBC0-41D2-BC14-C87D9B97D63B}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes_test", "_ctypes_test\_ctypes_test.vcproj", "{F548A318-960A-4B37-9CD6-86B1B0E33CC8}" ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED} = {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unicodedata", "unicodedata.vcproj", "{FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_elementtree", "_elementtree\_elementtree.vcproj", "{CB025148-F0A1-4B32-A669-19EE0534136D}" ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "w9xpopen", "w9xpopen.vcproj", "{E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_msi", "_msi\_msi.vcproj", "{A25ADCC5-8DE1-4F88-B842-C287923280B1}" + ProjectSection(ProjectDependencies) = postProject + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} + EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winsound", "winsound.vcproj", "{51F35FAE-FB92-4B2C-9187-1542C065AD77}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_sqlite3", "_sqlite3\_sqlite3.vcproj", "{D50E5319-41CC-429A-8E81-B1CD391C3A7B}" ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_elementtree", "_elementtree.vcproj", "{1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "python\python.vcproj", "{AE617428-B823-4B87-BC6D-DC7C12C746D3}" ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_buildinfo", "make_buildinfo.vcproj", "{C73F0EC1-358B-4177-940F-0846AC8B04CD}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythonw", "pythonw\pythonw.vcproj", "{98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}" + ProjectSection(ProjectDependencies) = postProject + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} + EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_msi", "_msi.vcproj", "{2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "select", "select\select.vcproj", "{0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}" ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes", "_ctypes.vcproj", "{F22F40F4-D318-40DC-96B3-88DC81CE0894}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unicodedata", "unicodedata\unicodedata.vcproj", "{D04B2089-7DA9-4D92-B23F-07453BC46652}" ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes_test", "_ctypes_test.vcproj", "{8CF334D9-4F82-42EB-97AF-83592C5AFD2F}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winsound", "winsound\winsound.vcproj", "{1015E3B4-FD3B-4402-AA6E-7806514156D6}" ProjectSection(ProjectDependencies) = postProject - {F22F40F4-D318-40DC-96B3-88DC81CE0894} = {F22F40F4-D318-40DC-96B3-88DC81CE0894} + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_sqlite3", "_sqlite3.vcproj", "{2FF0A312-22F9-4C34-B070-842916DE27A9}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_socket", "_socket\_socket.vcproj", "{AE31A248-5367-4EB2-A511-8722BC351CB4}" ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8B172265-1F31-4880-A29C-11A4B7A80172}" - ProjectSection(SolutionItems) = preProject - ..\Modules\getbuildinfo.c = ..\Modules\getbuildinfo.c - readme.txt = readme.txt +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_bsddb", "_bsddb\_bsddb.vcproj", "{E644B843-F7CA-4888-AA6D-653C77592856}" + ProjectSection(ProjectDependencies) = postProject + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "python.vcproj", "{B11D750F-CD1F-4A96-85CE-E69A5C5259F9}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testcapi", "_testcapi\_testcapi.vcproj", "{1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}" ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_versioninfo", "make_versioninfo.vcproj", "{F0E0541E-F17D-430B-97C4-93ADF0DD284E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_tkinter", "_tkinter\_tkinter.vcproj", "{3A1515AF-3694-4222-91F2-9837BDF60F9A}" + ProjectSection(ProjectDependencies) = postProject + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bz2", "bz2\bz2.vcproj", "{18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}" + ProjectSection(ProjectDependencies) = postProject + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pyexpat", "pyexpat\pyexpat.vcproj", "{80EBF51A-6018-4589-9A53-5AAF2872E230}" + ProjectSection(ProjectDependencies) = postProject + {987306EC-6BAD-4440-B4FB-A699A1EE6A28} = {987306EC-6BAD-4440-B4FB-A699A1EE6A28} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{310B6D98-CFE1-4215-97C1-E52989488A50}" + ProjectSection(SolutionItems) = preProject + readme.txt = readme.txt + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 - PGIRelease|Win32 = PGIRelease|Win32 - PGIRelease|x64 = PGIRelease|x64 - PGORelease|Win32 = PGORelease|Win32 - PGORelease|x64 = PGORelease|x64 + PGInstrument|Win32 = PGInstrument|Win32 + PGInstrument|x64 = PGInstrument|x64 + PGUpdate|Win32 = PGUpdate|Win32 + PGUpdate|x64 = PGUpdate|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Debug|Win32.ActiveCfg = Debug|Win32 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Debug|Win32.Build.0 = Debug|Win32 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Debug|x64.ActiveCfg = Debug|x64 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Debug|x64.Build.0 = Debug|x64 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.PGIRelease|Win32.ActiveCfg = PGIRelease|Win32 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.PGIRelease|Win32.Build.0 = PGIRelease|Win32 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.PGIRelease|x64.ActiveCfg = PGIRelease|x64 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.PGIRelease|x64.Build.0 = PGIRelease|x64 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.PGORelease|Win32.ActiveCfg = PGORelease|Win32 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.PGORelease|Win32.Build.0 = PGORelease|Win32 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.PGORelease|x64.ActiveCfg = PGORelease|x64 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.PGORelease|x64.Build.0 = PGORelease|x64 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Release|Win32.ActiveCfg = Release|Win32 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Release|Win32.Build.0 = Release|Win32 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Release|x64.ActiveCfg = Release|x64 - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Release|x64.Build.0 = Release|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Debug|Win32.ActiveCfg = Debug|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Debug|Win32.Build.0 = Debug|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Debug|x64.ActiveCfg = Debug|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Debug|x64.Build.0 = Debug|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGIRelease|Win32.Build.0 = Release|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGIRelease|x64.ActiveCfg = Release|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGIRelease|x64.Build.0 = Release|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGORelease|Win32.ActiveCfg = Release|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGORelease|Win32.Build.0 = Release|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGORelease|x64.ActiveCfg = Release|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGORelease|x64.Build.0 = Release|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Release|Win32.ActiveCfg = Release|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Release|Win32.Build.0 = Release|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Release|x64.ActiveCfg = Release|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Release|x64.Build.0 = Release|x64 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.Debug|Win32.ActiveCfg = Debug|Win32 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.Debug|Win32.Build.0 = Debug|Win32 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.Debug|x64.ActiveCfg = Debug|x64 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.Debug|x64.Build.0 = Debug|x64 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.PGIRelease|Win32.Build.0 = Release|Win32 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.PGIRelease|x64.ActiveCfg = Release|x64 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.PGIRelease|x64.Build.0 = Release|x64 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.PGORelease|Win32.ActiveCfg = Release|Win32 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.PGORelease|Win32.Build.0 = Release|Win32 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.PGORelease|x64.ActiveCfg = Release|x64 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.PGORelease|x64.Build.0 = Release|x64 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.Release|Win32.ActiveCfg = Release|Win32 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.Release|Win32.Build.0 = Release|Win32 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.Release|x64.ActiveCfg = Release|x64 - {97239A56-DBC0-41D2-BC14-C87D9B97D63B}.Release|x64.Build.0 = Release|x64 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.Debug|Win32.ActiveCfg = Debug|Win32 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.Debug|Win32.Build.0 = Debug|Win32 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.Debug|x64.ActiveCfg = Debug|x64 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.Debug|x64.Build.0 = Debug|x64 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.PGIRelease|Win32.Build.0 = Release|Win32 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.PGIRelease|x64.ActiveCfg = Release|x64 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.PGIRelease|x64.Build.0 = Release|x64 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.PGORelease|Win32.ActiveCfg = Release|Win32 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.PGORelease|Win32.Build.0 = Release|Win32 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.PGORelease|x64.ActiveCfg = Release|x64 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.PGORelease|x64.Build.0 = Release|x64 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.Release|Win32.ActiveCfg = Release|Win32 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.Release|Win32.Build.0 = Release|Win32 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.Release|x64.ActiveCfg = Release|x64 - {FA5FC7EB-C72F-415F-AE42-91DD605ABDDA}.Release|x64.Build.0 = Release|x64 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.Debug|Win32.ActiveCfg = Debug|Win32 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.Debug|Win32.Build.0 = Debug|Win32 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.Debug|x64.ActiveCfg = Debug|x64 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.Debug|x64.Build.0 = Debug|x64 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.PGIRelease|Win32.Build.0 = Release|Win32 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.PGIRelease|x64.ActiveCfg = Release|x64 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.PGIRelease|x64.Build.0 = Release|x64 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.PGORelease|Win32.ActiveCfg = Release|Win32 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.PGORelease|Win32.Build.0 = Release|Win32 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.PGORelease|x64.ActiveCfg = Release|x64 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.PGORelease|x64.Build.0 = Release|x64 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.Release|Win32.ActiveCfg = Release|Win32 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.Release|Win32.Build.0 = Release|Win32 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.Release|x64.ActiveCfg = Release|x64 - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}.Release|x64.Build.0 = Release|x64 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.Debug|Win32.ActiveCfg = Debug|Win32 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.Debug|Win32.Build.0 = Debug|Win32 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.Debug|x64.ActiveCfg = Debug|x64 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.Debug|x64.Build.0 = Debug|x64 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.PGIRelease|Win32.Build.0 = Release|Win32 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.PGIRelease|x64.ActiveCfg = Release|x64 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.PGIRelease|x64.Build.0 = Release|x64 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.PGORelease|Win32.ActiveCfg = Release|Win32 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.PGORelease|Win32.Build.0 = Release|Win32 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.PGORelease|x64.ActiveCfg = Release|x64 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.PGORelease|x64.Build.0 = Release|x64 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.Release|Win32.ActiveCfg = Release|Win32 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.Release|Win32.Build.0 = Release|Win32 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.Release|x64.ActiveCfg = Release|x64 - {51F35FAE-FB92-4B2C-9187-1542C065AD77}.Release|x64.Build.0 = Release|x64 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.Debug|Win32.ActiveCfg = Debug|Win32 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.Debug|Win32.Build.0 = Debug|Win32 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.Debug|x64.ActiveCfg = Debug|x64 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.Debug|x64.Build.0 = Debug|x64 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.PGIRelease|Win32.Build.0 = Release|Win32 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.PGIRelease|x64.ActiveCfg = Release|x64 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.PGIRelease|x64.Build.0 = Release|x64 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.PGORelease|Win32.ActiveCfg = Release|Win32 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.PGORelease|Win32.Build.0 = Release|Win32 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.PGORelease|x64.ActiveCfg = Release|x64 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.PGORelease|x64.Build.0 = Release|x64 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.Release|Win32.ActiveCfg = Release|Win32 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.Release|Win32.Build.0 = Release|Win32 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.Release|x64.ActiveCfg = Release|x64 - {1966DDE2-4AB7-4E4E-ACC9-C121E4D37F8E}.Release|x64.Build.0 = Release|x64 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.Debug|Win32.ActiveCfg = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.Debug|Win32.Build.0 = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.Debug|x64.ActiveCfg = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.Debug|x64.Build.0 = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.PGIRelease|Win32.ActiveCfg = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.PGIRelease|Win32.Build.0 = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.PGIRelease|x64.ActiveCfg = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.PGORelease|Win32.ActiveCfg = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.PGORelease|Win32.Build.0 = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.PGORelease|x64.ActiveCfg = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.Release|Win32.ActiveCfg = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.Release|Win32.Build.0 = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.Release|x64.ActiveCfg = Debug|Win32 - {C73F0EC1-358B-4177-940F-0846AC8B04CD}.Release|x64.Build.0 = Debug|Win32 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.Debug|Win32.ActiveCfg = Debug|Win32 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.Debug|Win32.Build.0 = Debug|Win32 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.Debug|x64.ActiveCfg = Debug|x64 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.Debug|x64.Build.0 = Debug|x64 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.PGIRelease|Win32.Build.0 = Release|Win32 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.PGIRelease|x64.ActiveCfg = Release|x64 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.PGIRelease|x64.Build.0 = Release|x64 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.PGORelease|Win32.ActiveCfg = Release|Win32 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.PGORelease|Win32.Build.0 = Release|Win32 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.PGORelease|x64.ActiveCfg = Release|x64 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.PGORelease|x64.Build.0 = Release|x64 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.Release|Win32.ActiveCfg = Release|Win32 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.Release|Win32.Build.0 = Release|Win32 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.Release|x64.ActiveCfg = Release|x64 - {2C0BEFB9-70E2-4F80-AC5B-4AB8EE023574}.Release|x64.Build.0 = Release|x64 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.Debug|Win32.ActiveCfg = Debug|Win32 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.Debug|Win32.Build.0 = Debug|Win32 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.Debug|x64.ActiveCfg = Debug|x64 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.Debug|x64.Build.0 = Debug|x64 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.PGIRelease|Win32.Build.0 = Release|Win32 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.PGIRelease|x64.ActiveCfg = Release|x64 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.PGIRelease|x64.Build.0 = Release|x64 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.PGORelease|Win32.ActiveCfg = Release|Win32 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.PGORelease|Win32.Build.0 = Release|Win32 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.PGORelease|x64.ActiveCfg = Release|x64 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.PGORelease|x64.Build.0 = Release|x64 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.Release|Win32.ActiveCfg = Release|Win32 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.Release|Win32.Build.0 = Release|Win32 - {F22F40F4-D318-40DC-96B3-88DC81CE0894}.Release|x64.ActiveCfg = Release|x64 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.Debug|Win32.ActiveCfg = Debug|Win32 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.Debug|Win32.Build.0 = Debug|Win32 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.Debug|x64.ActiveCfg = Debug|x64 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.Debug|x64.Build.0 = Debug|x64 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.PGIRelease|Win32.Build.0 = Release|Win32 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.PGIRelease|x64.ActiveCfg = Release|x64 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.PGIRelease|x64.Build.0 = Release|x64 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.PGORelease|Win32.ActiveCfg = Release|Win32 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.PGORelease|Win32.Build.0 = Release|Win32 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.PGORelease|x64.ActiveCfg = Release|x64 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.PGORelease|x64.Build.0 = Release|x64 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.Release|Win32.ActiveCfg = Release|Win32 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.Release|Win32.Build.0 = Release|Win32 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.Release|x64.ActiveCfg = Release|x64 - {8CF334D9-4F82-42EB-97AF-83592C5AFD2F}.Release|x64.Build.0 = Release|x64 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.Debug|Win32.ActiveCfg = Debug|Win32 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.Debug|Win32.Build.0 = Debug|Win32 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.Debug|x64.ActiveCfg = Debug|x64 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.Debug|x64.Build.0 = Debug|x64 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.PGIRelease|Win32.Build.0 = Release|Win32 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.PGIRelease|x64.ActiveCfg = Release|x64 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.PGIRelease|x64.Build.0 = Release|x64 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.PGORelease|Win32.ActiveCfg = Release|Win32 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.PGORelease|Win32.Build.0 = Release|Win32 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.PGORelease|x64.ActiveCfg = Release|x64 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.PGORelease|x64.Build.0 = Release|x64 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.Release|Win32.ActiveCfg = Release|Win32 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.Release|Win32.Build.0 = Release|Win32 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.Release|x64.ActiveCfg = Release|x64 - {2FF0A312-22F9-4C34-B070-842916DE27A9}.Release|x64.Build.0 = Release|x64 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Debug|Win32.ActiveCfg = Debug|Win32 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Debug|Win32.Build.0 = Debug|Win32 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Debug|x64.ActiveCfg = Debug|x64 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Debug|x64.Build.0 = Debug|x64 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.PGIRelease|Win32.Build.0 = Release|Win32 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.PGIRelease|x64.ActiveCfg = Release|x64 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.PGIRelease|x64.Build.0 = Release|x64 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.PGORelease|Win32.ActiveCfg = Release|Win32 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.PGORelease|Win32.Build.0 = Release|Win32 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.PGORelease|x64.ActiveCfg = Release|x64 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.PGORelease|x64.Build.0 = Release|x64 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Release|Win32.ActiveCfg = Release|Win32 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Release|Win32.Build.0 = Release|Win32 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Release|x64.ActiveCfg = Release|x64 - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Release|x64.Build.0 = Release|x64 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Debug|Win32.ActiveCfg = Debug|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Debug|Win32.Build.0 = Debug|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Debug|x64.ActiveCfg = Debug|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Debug|x64.Build.0 = Debug|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGIRelease|Win32.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGIRelease|Win32.Build.0 = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGIRelease|x64.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGORelease|Win32.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGORelease|Win32.Build.0 = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGORelease|x64.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Release|Win32.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Release|Win32.Build.0 = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Release|x64.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Release|x64.Build.0 = Release|Win32 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.Debug|Win32.ActiveCfg = Debug|Win32 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.Debug|Win32.Build.0 = Debug|Win32 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.Debug|x64.ActiveCfg = Debug|x64 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.Debug|x64.Build.0 = Debug|x64 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.Release|Win32.ActiveCfg = Release|Win32 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.Release|Win32.Build.0 = Release|Win32 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.Release|x64.ActiveCfg = Release|x64 + {987306EC-6BAD-4440-B4FB-A699A1EE6A28}.Release|x64.Build.0 = Release|x64 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.Debug|Win32.Build.0 = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.Debug|x64.ActiveCfg = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.Debug|x64.Build.0 = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.PGInstrument|Win32.ActiveCfg = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.PGInstrument|Win32.Build.0 = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.PGInstrument|x64.ActiveCfg = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.PGUpdate|Win32.ActiveCfg = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.PGUpdate|Win32.Build.0 = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.PGUpdate|x64.ActiveCfg = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.Release|Win32.ActiveCfg = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.Release|Win32.Build.0 = Debug|Win32 + {2AB2AC43-1B73-40B1-8964-95B3FC3F15ED}.Release|x64.ActiveCfg = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.Debug|Win32.ActiveCfg = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.Debug|Win32.Build.0 = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.Debug|x64.ActiveCfg = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.Debug|x64.Build.0 = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.PGInstrument|Win32.ActiveCfg = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.PGInstrument|Win32.Build.0 = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.PGInstrument|x64.ActiveCfg = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.PGUpdate|Win32.ActiveCfg = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.PGUpdate|Win32.Build.0 = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.PGUpdate|x64.ActiveCfg = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.Release|Win32.ActiveCfg = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.Release|Win32.Build.0 = Debug|Win32 + {87AB87DB-B665-4621-A67B-878C15B93FF0}.Release|x64.ActiveCfg = Debug|Win32 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.Debug|Win32.Build.0 = Debug|Win32 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.Debug|x64.ActiveCfg = Debug|x64 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.Debug|x64.Build.0 = Debug|x64 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.Release|Win32.ActiveCfg = Release|Win32 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.Release|Win32.Build.0 = Release|Win32 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.Release|x64.ActiveCfg = Release|x64 + {8D80F68B-F6EC-4E69-9B04-73F632A8A8ED}.Release|x64.Build.0 = Release|x64 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.Debug|Win32.ActiveCfg = Debug|Win32 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.Debug|Win32.Build.0 = Debug|Win32 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.Debug|x64.ActiveCfg = Debug|x64 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.Debug|x64.Build.0 = Debug|x64 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.Release|Win32.ActiveCfg = Release|Win32 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.Release|Win32.Build.0 = Release|Win32 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.Release|x64.ActiveCfg = Release|x64 + {F548A318-960A-4B37-9CD6-86B1B0E33CC8}.Release|x64.Build.0 = Release|x64 + {CB025148-F0A1-4B32-A669-19EE0534136D}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB025148-F0A1-4B32-A669-19EE0534136D}.Debug|Win32.Build.0 = Debug|Win32 + {CB025148-F0A1-4B32-A669-19EE0534136D}.Debug|x64.ActiveCfg = Debug|x64 + {CB025148-F0A1-4B32-A669-19EE0534136D}.Debug|x64.Build.0 = Debug|x64 + {CB025148-F0A1-4B32-A669-19EE0534136D}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {CB025148-F0A1-4B32-A669-19EE0534136D}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {CB025148-F0A1-4B32-A669-19EE0534136D}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {CB025148-F0A1-4B32-A669-19EE0534136D}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {CB025148-F0A1-4B32-A669-19EE0534136D}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {CB025148-F0A1-4B32-A669-19EE0534136D}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {CB025148-F0A1-4B32-A669-19EE0534136D}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {CB025148-F0A1-4B32-A669-19EE0534136D}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {CB025148-F0A1-4B32-A669-19EE0534136D}.Release|Win32.ActiveCfg = Release|Win32 + {CB025148-F0A1-4B32-A669-19EE0534136D}.Release|Win32.Build.0 = Release|Win32 + {CB025148-F0A1-4B32-A669-19EE0534136D}.Release|x64.ActiveCfg = Release|x64 + {CB025148-F0A1-4B32-A669-19EE0534136D}.Release|x64.Build.0 = Release|x64 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.Debug|Win32.ActiveCfg = Debug|Win32 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.Debug|Win32.Build.0 = Debug|Win32 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.Debug|x64.ActiveCfg = Debug|x64 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.Debug|x64.Build.0 = Debug|x64 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.Release|Win32.ActiveCfg = Release|Win32 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.Release|Win32.Build.0 = Release|Win32 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.Release|x64.ActiveCfg = Release|x64 + {A25ADCC5-8DE1-4F88-B842-C287923280B1}.Release|x64.Build.0 = Release|x64 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.Debug|Win32.ActiveCfg = Debug|Win32 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.Debug|Win32.Build.0 = Debug|Win32 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.Debug|x64.ActiveCfg = Debug|x64 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.Debug|x64.Build.0 = Debug|x64 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.Release|Win32.ActiveCfg = Release|Win32 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.Release|Win32.Build.0 = Release|Win32 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.Release|x64.ActiveCfg = Release|x64 + {D50E5319-41CC-429A-8E81-B1CD391C3A7B}.Release|x64.Build.0 = Release|x64 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.Debug|Win32.ActiveCfg = Debug|Win32 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.Debug|Win32.Build.0 = Debug|Win32 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.Debug|x64.ActiveCfg = Debug|x64 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.Debug|x64.Build.0 = Debug|x64 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.Release|Win32.ActiveCfg = Release|Win32 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.Release|Win32.Build.0 = Release|Win32 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.Release|x64.ActiveCfg = Release|x64 + {AE617428-B823-4B87-BC6D-DC7C12C746D3}.Release|x64.Build.0 = Release|x64 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.Debug|Win32.ActiveCfg = Debug|Win32 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.Debug|Win32.Build.0 = Debug|Win32 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.Debug|x64.ActiveCfg = Debug|x64 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.Debug|x64.Build.0 = Debug|x64 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.Release|Win32.ActiveCfg = Release|Win32 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.Release|Win32.Build.0 = Release|Win32 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.Release|x64.ActiveCfg = Release|x64 + {98C3DB47-DD1F-4A4B-9D3C-1DBB32AC6667}.Release|x64.Build.0 = Release|x64 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.Debug|Win32.ActiveCfg = Debug|Win32 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.Debug|Win32.Build.0 = Debug|Win32 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.Debug|x64.ActiveCfg = Debug|x64 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.Debug|x64.Build.0 = Debug|x64 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.Release|Win32.ActiveCfg = Release|Win32 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.Release|Win32.Build.0 = Release|Win32 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.Release|x64.ActiveCfg = Release|x64 + {0BAFC4A4-8DB5-4CC6-9DDB-A1D32C682B2F}.Release|x64.Build.0 = Release|x64 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.Debug|Win32.ActiveCfg = Debug|Win32 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.Debug|Win32.Build.0 = Debug|Win32 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.Debug|x64.ActiveCfg = Debug|x64 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.Debug|x64.Build.0 = Debug|x64 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.Release|Win32.ActiveCfg = Release|Win32 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.Release|Win32.Build.0 = Release|Win32 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.Release|x64.ActiveCfg = Release|x64 + {D04B2089-7DA9-4D92-B23F-07453BC46652}.Release|x64.Build.0 = Release|x64 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.Debug|Win32.ActiveCfg = Debug|Win32 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.Debug|Win32.Build.0 = Debug|Win32 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.Debug|x64.ActiveCfg = Debug|x64 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.Debug|x64.Build.0 = Debug|x64 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.Release|Win32.ActiveCfg = Release|Win32 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.Release|Win32.Build.0 = Release|Win32 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.Release|x64.ActiveCfg = Release|x64 + {1015E3B4-FD3B-4402-AA6E-7806514156D6}.Release|x64.Build.0 = Release|x64 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.Debug|Win32.ActiveCfg = Debug|Win32 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.Debug|Win32.Build.0 = Debug|Win32 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.Debug|x64.ActiveCfg = Debug|x64 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.Debug|x64.Build.0 = Debug|x64 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.Release|Win32.ActiveCfg = Release|Win32 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.Release|Win32.Build.0 = Release|Win32 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.Release|x64.ActiveCfg = Release|x64 + {AE31A248-5367-4EB2-A511-8722BC351CB4}.Release|x64.Build.0 = Release|x64 + {E644B843-F7CA-4888-AA6D-653C77592856}.Debug|Win32.ActiveCfg = Debug|Win32 + {E644B843-F7CA-4888-AA6D-653C77592856}.Debug|Win32.Build.0 = Debug|Win32 + {E644B843-F7CA-4888-AA6D-653C77592856}.Debug|x64.ActiveCfg = Debug|x64 + {E644B843-F7CA-4888-AA6D-653C77592856}.Debug|x64.Build.0 = Debug|x64 + {E644B843-F7CA-4888-AA6D-653C77592856}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {E644B843-F7CA-4888-AA6D-653C77592856}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {E644B843-F7CA-4888-AA6D-653C77592856}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {E644B843-F7CA-4888-AA6D-653C77592856}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {E644B843-F7CA-4888-AA6D-653C77592856}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {E644B843-F7CA-4888-AA6D-653C77592856}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {E644B843-F7CA-4888-AA6D-653C77592856}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {E644B843-F7CA-4888-AA6D-653C77592856}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {E644B843-F7CA-4888-AA6D-653C77592856}.Release|Win32.ActiveCfg = PGInstrument|Win32 + {E644B843-F7CA-4888-AA6D-653C77592856}.Release|Win32.Build.0 = PGInstrument|Win32 + {E644B843-F7CA-4888-AA6D-653C77592856}.Release|x64.ActiveCfg = Release|x64 + {E644B843-F7CA-4888-AA6D-653C77592856}.Release|x64.Build.0 = Release|x64 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.Debug|Win32.ActiveCfg = Debug|Win32 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.Debug|Win32.Build.0 = Debug|Win32 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.Debug|x64.ActiveCfg = Debug|x64 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.Debug|x64.Build.0 = Debug|x64 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.Release|Win32.ActiveCfg = Release|Win32 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.Release|Win32.Build.0 = Release|Win32 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.Release|x64.ActiveCfg = Release|x64 + {1E8DCFC4-1EF8-4076-8CA2-B08D3C979749}.Release|x64.Build.0 = Release|x64 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.Debug|Win32.ActiveCfg = Debug|Win32 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.Debug|Win32.Build.0 = Debug|Win32 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.Debug|x64.ActiveCfg = Debug|x64 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.Debug|x64.Build.0 = Debug|x64 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.Release|Win32.ActiveCfg = Release|Win32 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.Release|Win32.Build.0 = Release|Win32 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.Release|x64.ActiveCfg = Release|x64 + {3A1515AF-3694-4222-91F2-9837BDF60F9A}.Release|x64.Build.0 = Release|x64 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.Debug|Win32.ActiveCfg = Debug|Win32 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.Debug|Win32.Build.0 = Debug|Win32 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.Debug|x64.ActiveCfg = Debug|x64 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.Debug|x64.Build.0 = Debug|x64 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.Release|Win32.ActiveCfg = Release|Win32 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.Release|Win32.Build.0 = Release|Win32 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.Release|x64.ActiveCfg = Release|x64 + {18C518FB-33CB-4C16-AA05-8DEA8DE66DF0}.Release|x64.Build.0 = Release|x64 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.Debug|Win32.ActiveCfg = Debug|Win32 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.Debug|Win32.Build.0 = Debug|Win32 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.Debug|x64.ActiveCfg = Debug|x64 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.Debug|x64.Build.0 = Debug|x64 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.Release|Win32.ActiveCfg = Release|Win32 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.Release|Win32.Build.0 = Release|Win32 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.Release|x64.ActiveCfg = Release|x64 + {80EBF51A-6018-4589-9A53-5AAF2872E230}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Added: python/trunk/PCbuild8/pyd.vsprops ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/pyd.vsprops Mon Apr 30 17:17:46 2007 @@ -0,0 +1,13 @@ + + + + Added: python/trunk/PCbuild8/pyd_d.vsprops ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/pyd_d.vsprops Mon Apr 30 17:17:46 2007 @@ -0,0 +1,14 @@ + + + + Deleted: /python/trunk/PCbuild8/pyexpat.vcproj ============================================================================== --- /python/trunk/PCbuild8/pyexpat.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,393 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/pyexpat/pyexpat.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/pyexpat/pyexpat.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,664 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: python/trunk/PCbuild8/pyproject.vsprops ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/pyproject.vsprops Mon Apr 30 17:17:46 2007 @@ -0,0 +1,34 @@ + + + + + + + + + Deleted: /python/trunk/PCbuild8/python.build ============================================================================== --- /python/trunk/PCbuild8/python.build Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - Deleted: /python/trunk/PCbuild8/python.iss ============================================================================== --- /python/trunk/PCbuild8/python.iss Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,346 +0,0 @@ -; Script generated by the Inno Setup Script Wizard. -; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! - -; This is the whole ball of wax for an Inno installer for Python. -; To use, download Inno Setup from http://www.jrsoftware.org/isdl.htm/, -; install it, and double-click on this file. That launches the Inno -; script compiler. The GUI is extemely simple, and has only one button -; you may not recognize instantly: click it. You're done. It builds -; the installer into PCBuild/Python-2.2a1.exe. Size and speed of the -; installer are competitive with the Wise installer; Inno uninstall -; seems much quicker than Wise (but also feebler, and the uninstall -; log is in some un(human)readable binary format). -; -; What's Done -; ----------- -; All the usual Windows Python files are installed by this now. -; All the usual Windows Python Start menu entries are created and -; work fine. -; .py, .pyw, .pyc and .pyo extensions are registered. -; PROBLEM: Inno uninstall does not restore their previous registry -; associations (if any). Wise did. This will make life -; difficult for alpha (etc) testers. -; The Python install is fully functional for "typical" uses. -; -; What's Not Done -; --------------- -; None of "Mark Hammond's" registry entries are written. -; No installation of files is done into the system dir: -; The MS DLLs aren't handled at all by this yet. -; Python22.dll is unpacked into the main Python dir. -; -; Inno can't do different things on NT/2000 depending on whether the user -; has Admin privileges, so I don't know how to "solve" either of those, -; short of building two installers (one *requiring* Admin privs, the -; other not doing anything that needs Admin privs). -; -; Inno has no concept of variables, so lots of lines in this file need -; to be fiddled by hand across releases. Simplest way out: stick this -; file in a giant triple-quoted r-string (note that backslashes are -; required all over the place here -- forward slashes DON'T WORK in -; Inno), and use %(yadda)s string interpolation to do substitutions; i.e., -; write a very simple Python program to *produce* this script. - -[Setup] -AppName=Python and combined Win32 Extensions -AppVerName=Python 2.2.2 and combined Win32 Extensions 150 -AppId=Python 2.2.2.150 -AppVersion=2.2.2.150 -AppCopyright=Python is Copyright ? 2001 Python Software Foundation. Win32 Extensions are Copyright ? 1996-2001 Greg Stein and Mark Hammond. - -; Default install dir; value of {app} later (unless user overrides). -; {sd} = system root drive, probably "C:". -DefaultDirName={sd}\Python22 -;DefaultDirName={pf}\Python - -; Start menu folder name; value of {group} later (unless user overrides). -DefaultGroupName=Python 2.2 - -; Point SourceDir to one above PCBuild = src. -; means this script can run unchanged from anyone's CVS tree, no matter -; what they called the top-level directories. -SourceDir=. -OutputDir=.. -OutputBaseFilename=Python-2.2.2-Win32-150-Setup - -AppPublisher=PythonLabs at Digital Creations -AppPublisherURL=http://www.python.org -AppSupportURL=http://www.python.org -AppUpdatesURL=http://www.python.org - -AlwaysCreateUninstallIcon=true -ChangesAssociations=true -UninstallLogMode=new -AllowNoIcons=true -AdminPrivilegesRequired=true -UninstallDisplayIcon={app}\pyc.ico -WizardDebug=false - -; The fewer screens the better; leave these commented. - -Compression=bzip -InfoBeforeFile=LICENSE.txt -;InfoBeforeFile=Misc\NEWS - -; uncomment the following line if you want your installation to run on NT 3.51 too. -; MinVersion=4,3.51 - -[Types] -Name: normal; Description: Select desired components; Flags: iscustom - -[Components] -Name: main; Description: Python and Win32 Extensions; Types: normal -Name: docs; Description: Python documentation (HTML); Types: normal -Name: tk; Description: TCL/TK, tkinter, and Idle; Types: normal -Name: tools; Description: Python utility scripts (Tools\); Types: normal -Name: test; Description: Python test suite (Lib\test\); Types: normal - -[Tasks] -Name: extensions; Description: Register file associations (.py, .pyw, .pyc, .pyo); Components: main; Check: IsAdminLoggedOn - -[Files] -; Caution: Using forward slashes instead screws up in amazing ways. -; Unknown: By the time Components (and other attrs) are added to these lines, they're -; going to get awfully long. But don't see a way to continue logical lines across -; physical lines. - -Source: LICENSE.txt; DestDir: {app}; CopyMode: alwaysoverwrite -Source: README.txt; DestDir: {app}; CopyMode: alwaysoverwrite -Source: News.txt; DestDir: {app}; CopyMode: alwaysoverwrite -Source: *.ico; DestDir: {app}; CopyMode: alwaysoverwrite; Components: main - -Source: python.exe; DestDir: {app}; CopyMode: alwaysoverwrite; Components: main -Source: pythonw.exe; DestDir: {app}; CopyMode: alwaysoverwrite; Components: main -Source: w9xpopen.exe; DestDir: {app}; CopyMode: alwaysoverwrite; Components: main - - -Source: DLLs\tcl83.dll; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: tk -Source: DLLs\tk83.dll; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: tk -Source: tcl\*.*; DestDir: {app}\tcl; CopyMode: alwaysoverwrite; Components: tk; Flags: recursesubdirs - -Source: sysdir\python22.dll; DestDir: {sys}; CopyMode: alwaysskipifsameorolder; Components: main; Flags: sharedfile restartreplace -Source: sysdir\PyWinTypes22.dll; DestDir: {sys}; CopyMode: alwaysskipifsameorolder; Components: main; Flags: restartreplace sharedfile -Source: sysdir\pythoncom22.dll; DestDir: {sys}; CopyMode: alwaysskipifsameorolder; Components: main; Flags: restartreplace sharedfile - -Source: DLLs\_socket.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\_socket.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\_sre.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\_sre.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\_symtable.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\_symtable.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\_testcapi.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\_testcapi.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\_tkinter.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: tk -Source: libs\_tkinter.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: tk - -Source: DLLs\bsddb.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\bsddb.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\mmap.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\mmap.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\parser.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\parser.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\pyexpat.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\pyexpat.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\select.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\select.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\unicodedata.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\unicodedata.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\_winreg.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\_winreg.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\winsound.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\winsound.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\zlib.pyd; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main -Source: libs\zlib.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: libs\python22.lib; DestDir: {app}\libs; CopyMode: alwaysoverwrite; Components: main - -Source: DLLs\expat.dll; DestDir: {app}\DLLs; CopyMode: alwaysoverwrite; Components: main - - - -Source: Lib\*.py; DestDir: {app}\Lib; CopyMode: alwaysoverwrite; Components: main -Source: Lib\compiler\*.*; DestDir: {app}\Lib\compiler; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\distutils\*.*; DestDir: {app}\Lib\distutils; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\email\*.*; DestDir: {app}\Lib\email; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\encodings\*.*; DestDir: {app}\Lib\encodings; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\hotshot\*.*; DestDir: {app}\Lib\hotshot; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\lib-old\*.*; DestDir: {app}\Lib\lib-old; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\xml\*.*; DestDir: {app}\Lib\xml; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\hotshot\*.*; DestDir: {app}\Lib\hotshot; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\test\*.*; DestDir: {app}\Lib\test; CopyMode: alwaysoverwrite; Components: test; Flags: recursesubdirs - -Source: Lib\site-packages\README.txt; DestDir: {app}\Lib\site-packages; CopyMode: alwaysoverwrite; Components: main - -Source: Lib\site-packages\PyWin32.chm; DestDir: {app}\Lib\site-packages; CopyMode: alwaysoverwrite; Components: docs -Source: Lib\site-packages\win32\*.*; DestDir: {app}\Lib\site-packages\win32; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\site-packages\win32com\*.*; DestDir: {app}\Lib\site-packages\win32com; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs -Source: Lib\site-packages\win32comext\*.*; DestDir: {app}\Lib\site-packages\win32comext; CopyMode: alwaysoverwrite; Components: main; Flags: recursesubdirs - -Source: Lib\lib-tk\*.py; DestDir: {app}\Lib\lib-tk; CopyMode: alwaysoverwrite; Components: tk; Flags: recursesubdirs - -Source: include\*.h; DestDir: {app}\include; CopyMode: alwaysoverwrite; Components: main - -Source: Tools\idle\*.*; DestDir: {app}\Tools\idle; CopyMode: alwaysoverwrite; Components: tk; Flags: recursesubdirs - -Source: Tools\pynche\*.*; DestDir: {app}\Tools\pynche; CopyMode: alwaysoverwrite; Components: tools; Flags: recursesubdirs -Source: Tools\scripts\*.*; DestDir: {app}\Tools\Scripts; CopyMode: alwaysoverwrite; Components: tools; Flags: recursesubdirs -Source: Tools\webchecker\*.*; DestDir: {app}\Tools\webchecker; CopyMode: alwaysoverwrite; Components: tools; Flags: recursesubdirs -Source: Tools\versioncheck\*.*; DestDir: {app}\Tools\versioncheck; CopyMode: alwaysoverwrite; Components: tools; Flags: recursesubdirs - -Source: Doc\*.*; DestDir: {app}\Doc; CopyMode: alwaysoverwrite; Flags: recursesubdirs; Components: docs - - -[Icons] -Name: {group}\Python (command line); Filename: {app}\python.exe; WorkingDir: {app}; Components: main -Name: {group}\Python Manuals; Filename: {app}\Doc\index.html; WorkingDir: {app}; Components: docs -Name: {group}\Win32 Extensions Help; Filename: {app}\Lib\site-packages\PyWin32.chm; WorkingDir: {app}\Lib\site-packages; Components: docs -Name: {group}\Module Docs; Filename: {app}\pythonw.exe; WorkingDir: {app}; Parameters: """{app}\Tools\Scripts\pydoc.pyw"""; Components: tools -Name: {group}\IDLE (Python GUI); Filename: {app}\pythonw.exe; WorkingDir: {app}; Parameters: """{app}\Tools\idle\idle.pyw"""; Components: tools - -[Registry] -; Register .py -Tasks: extensions; Root: HKCR; Subkey: .py; ValueType: string; ValueName: ; ValueData: Python File; Flags: uninsdeletevalue -Tasks: extensions; Root: HKCR; Subkey: .py; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: uninsdeletevalue -Tasks: extensions; Root: HKCR; Subkey: Python File; ValueType: string; ValueName: ; ValueData: Python File; Flags: uninsdeletekey -Tasks: extensions; Root: HKCR; Subkey: Python File\DefaultIcon; ValueType: string; ValueName: ; ValueData: {app}\Py.ico -Tasks: extensions; Root: HKCR; Subkey: Python File\shell\open\command; ValueType: string; ValueName: ; ValueData: """{app}\python.exe"" ""%1"" %*" - -; Register .pyc -Tasks: extensions; Root: HKCR; Subkey: .pyc; ValueType: string; ValueName: ; ValueData: Python CompiledFile; Flags: uninsdeletevalue -Tasks: extensions; Root: HKCR; Subkey: Python CompiledFile; ValueType: string; ValueName: ; ValueData: Compiled Python File; Flags: uninsdeletekey -Tasks: extensions; Root: HKCR; Subkey: Python CompiledFile\DefaultIcon; ValueType: string; ValueName: ; ValueData: {app}\pyc.ico -Tasks: extensions; Root: HKCR; Subkey: Python CompiledFile\shell\open\command; ValueType: string; ValueName: ; ValueData: """{app}\python.exe"" ""%1"" %*" - -; Register .pyo -Tasks: extensions; Root: HKCR; Subkey: .pyo; ValueType: string; ValueName: ; ValueData: Python CompiledFile; Flags: uninsdeletevalue - -; Register .pyw -Tasks: extensions; Root: HKCR; Subkey: .pyw; ValueType: string; ValueName: ; ValueData: Python NoConFile; Flags: uninsdeletevalue -Tasks: extensions; Root: HKCR; Subkey: .pyw; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: uninsdeletevalue -Tasks: extensions; Root: HKCR; Subkey: Python NoConFile; ValueType: string; ValueName: ; ValueData: Python File (no console); Flags: uninsdeletekey -Tasks: extensions; Root: HKCR; Subkey: Python NoConFile\DefaultIcon; ValueType: string; ValueName: ; ValueData: {app}\Py.ico -Tasks: extensions; Root: HKCR; Subkey: Python NoConFile\shell\open\command; ValueType: string; ValueName: ; ValueData: """{app}\pythonw.exe"" ""%1"" %*" - - -; Python Registry Keys -Root: HKLM; Subkey: SOFTWARE\Python; Flags: uninsdeletekeyifempty; Check: IsAdminLoggedOn -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore; Flags: uninsdeletekeyifempty -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2; Flags: uninsdeletekeyifempty -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\PythonPath; ValueData: "{app}\Lib;{app}\DLLs"; Flags: uninsdeletekeyifempty -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\PythonPath\tk; ValueData: {app}\Lib\lib-tk; Flags: uninsdeletekey; Components: tk -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\PythonPath\win32; ValueData: "{app}\lib\site-packages\win32;{app}\lib\site-packages\win32\lib"; Flags: uninsdeletekey -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\PythonPath\win32com; ValueData: C:\Python\lib\site-packages; Flags: uninsdeletekey -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\Modules; Flags: uninsdeletekeyifempty -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\Modules\pythoncom; ValueData: {sys}\pythoncom22.dll; Flags: uninsdeletekey -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\Modules\pywintypes; ValueData: {sys}\PyWinTypes22.dll; Flags: uninsdeletekey -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\InstallPath; ValueData: {app}; Flags: uninsdeletekeyifempty; ValueType: string -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\InstallPath\InstallGroup; ValueData: {group}; Flags: uninsdeletekey -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\Help; Flags: uninsdeletekeyifempty -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\Help\Main Python Documentation; ValueType: string; ValueData: {app}\Doc\index.html; Flags: uninsdeletekey; Components: docs -Root: HKLM; Subkey: SOFTWARE\Python\PythonCore\2.2\Help\Python Win32 Documentation; ValueType: string; ValueData: {app}\lib\site-packages\PyWin32.chm; Flags: uninsdeletekey; Components: docs - -[_ISTool] -EnableISX=true - - -[Code] -Program Setup; - -Function IsAdminNotLoggedOn(): Boolean; -begin - Result := Not IsAdminLoggedOn(); -end; - -begin -end. - - - - -[UninstallDelete] -Name: {app}\Lib\compiler\*.pyc; Type: files -Name: {app}\Lib\compiler\*.pyo; Type: files -Name: {app}\Lib\compiler; Type: dirifempty -Name: {app}\Lib\distutils\command\*.pyc; Type: files -Name: {app}\Lib\distutils\command\*.pyo; Type: files -Name: {app}\Lib\distutils\command; Type: dirifempty -Name: {app}\Lib\distutils\*.pyc; Type: files -Name: {app}\Lib\distutils\*.pyo; Type: files -Name: {app}\Lib\distutils; Type: dirifempty -Name: {app}\Lib\email\test\*.pyc; Type: files -Name: {app}\Lib\email\test\*.pyo; Type: files -Name: {app}\Lib\email\test; Type: dirifempty -Name: {app}\Lib\email\*.pyc; Type: files -Name: {app}\Lib\email\*.pyo; Type: files -Name: {app}\Lib\email; Type: dirifempty -Name: {app}\Lib\encodings\*.pyc; Type: files -Name: {app}\Lib\encodings\*.pyo; Type: files -Name: {app}\Lib\encodings; Type: dirifempty -Name: {app}\Lib\hotshot\*.pyc; Type: files -Name: {app}\Lib\hotshot\*.pyo; Type: files -Name: {app}\Lib\hotshot; Type: dirifempty -Name: {app}\Lib\lib-old\*.pyc; Type: files -Name: {app}\Lib\lib-old\*.pyo; Type: files -Name: {app}\Lib\lib-old; Type: dirifempty -Name: {app}\Lib\lib-tk\*.pyc; Type: files -Name: {app}\Lib\lib-tk\*.pyo; Type: files -Name: {app}\Lib\lib-tk; Type: dirifempty -Name: {app}\Lib\test\*.pyc; Type: files -Name: {app}\Lib\test\*.pyo; Type: files -Name: {app}\Lib\test; Type: dirifempty -Name: {app}\Lib\xml\dom\*.pyc; Type: files -Name: {app}\Lib\xml\dom\*.pyo; Type: files -Name: {app}\Lib\xml\dom; Type: dirifempty -Name: {app}\Lib\xml\parsers\*.pyc; Type: files -Name: {app}\Lib\xml\parsers\*.pyo; Type: files -Name: {app}\Lib\xml\parsers; Type: dirifempty -Name: {app}\Lib\xml\sax\*.pyc; Type: files -Name: {app}\Lib\xml\sax\*.pyo; Type: files -Name: {app}\Lib\xml\sax; Type: dirifempty -Name: {app}\Lib\xml\*.pyc; Type: files -Name: {app}\Lib\xml\*.pyo; Type: files -Name: {app}\Lib\xml; Type: dirifempty - -Name: {app}\Lib\site-packages\win32; Type: filesandordirs -Name: {app}\Lib\site-packages\win32com; Type: filesandordirs -Name: {app}\Lib\site-packages\win32comext; Type: filesandordirs -Name: {app}\Lib\site-packages\pythoncom.py*; Type: files -Name: {app}\Lib\site-packages; Type: dirifempty - -Name: {app}\Lib\*.pyc; Type: files -Name: {app}\Lib; Type: dirifempty - -Name: {app}\Tools\pynche\*.pyc; Type: files -Name: {app}\Tools\pynche\*.pyo; Type: files -Name: {app}\Tools\pynche; Type: dirifempty - -Name: {app}\Tools\idle\*.pyc; Type: files -Name: {app}\Tools\idle\*.pyo; Type: files -Name: {app}\Tools\idle; Type: dirifempty - -Name: {app}\Tools\scripts\*.pyc; Type: files -Name: {app}\Tools\scripts\*.pyo; Type: files -Name: {app}\Tools\scripts; Type: dirifempty - -Name: {app}\Tools\versioncheck\*.pyc; Type: files -Name: {app}\Tools\versioncheck\*.pyo; Type: files -Name: {app}\Tools\versioncheck; Type: dirifempty - -Name: {app}\Tools\webchecker\*.pyc; Type: files -Name: {app}\Tools\webchecker\*.pyo; Type: files -Name: {app}\Tools\webchecker; Type: dirifempty - -Name: {app}\Tools; Type: dirifempty - Deleted: /python/trunk/PCbuild8/python.vcproj ============================================================================== --- /python/trunk/PCbuild8/python.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,399 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/python/python.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/python/python.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,654 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/python20.wse ============================================================================== --- /python/trunk/PCbuild8/python20.wse Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,3135 +0,0 @@ -Document Type: WSE -item: Global - Version=9.0 - Title=Python 2.4a1 - Flags=00010100 - Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - Japanese Font Name=MS Gothic - Japanese Font Size=10 - Start Gradient=0 255 0 - End Gradient=0 128 0 - Windows Flags=00000100000011010010010100001010 - Log Pathname=%MAINDIR%\INSTALL.LOG - Message Font=MS Sans Serif - Font Size=8 - Pages Modified=00010000011101000000000100000111 - Extra Pages=00000000000000000000000010110010 - Disk Filename=SETUP - Patch Flags=0000000000001001 - Patch Threshold=85 - Patch Memory=4000 - MIF PDF Version=1.0 - MIF SMS Version=2.0 - EXE Filename=Python-2.4a1.exe - Dialogs Version=8 - Version File=2.4a1 - Version Description=Python Programming Language - Version Copyright=?2001-2007 Python Software Foundation - Version Company=Python Software Foundation - Crystal Format=10111100101100000010001001001001 - Step View=&All - Variable Name1=_WISE_ - Variable Description1=WISE root directory - Variable Default1=C:\Programme\Wise Installation System - Variable Flags1=00001000 - Variable Name2=_TCLDIR_ - Variable Description2=The directory in which the Tcl/Tk installation - Variable Description2=lives. This must be a sibling of the Python - Variable Description2=directory. - Variable Default2=tcl84 - Variable Flags2=00001000 - Variable Name3=_DOC_ - Variable Description3=The unpacked HTML doc directory. - Variable Default3=..\html - Variable Flags3=00001001 - Variable Name4=_SYS_ - Variable Description4=System directory (where to find MSVCRT.DLL) - Variable Default4=C:\Windows\System - Variable Values4=C:\Windows\System - Variable Values4=C:\WINNT\System32 - Variable Values4=C:\Code\MSDLLs - Variable Values4=C:\Windows\System32 - Variable Flags4=00000010 - Variable Name5=_PYMAJOR_ - Variable Description5=Python major version number; the 2 in 2.3. - Variable Default5=2 - Variable Flags5=00001000 - Variable Name6=_PYMINOR_ - Variable Description6=Python minor version number; the 3 in 2.3 - Variable Default6=3 - Variable Flags6=00001000 - Variable Name7=_DOADMIN_ - Variable Description7=The initial value for %DOADMIN%. - Variable Description7=When 0, we never try to write under HKLM, - Variable Description7=and install the Python + MS runtime DLLs in - Variable Description7=the Python directory instead of the system dir. - Variable Default7=1 - Variable Values7=1 - Variable Values7=0 - Variable Flags7=00001010 - Variable Name8=_ALIASNAME_ - Variable Flags8=00001000 - Variable Name9=_ALIASPATH_ - Variable Flags9=00001000 - Variable Name10=_ALIASTYPE_ - Variable Flags10=00001000 -end -item: Set Variable - Variable=PYVER_STRING - Value=2.3 -end -item: Remark -end -item: Remark - Text=When the version number changes, set the compiler -end -item: Remark - Text=vrbls _PYMAJOR_ and _PYMINOR_. -end -item: Remark - Text=Nothing in the script below should need fiddling then. -end -item: Remark - Text=Other things that need fiddling: -end -item: Remark - Text= PYVER_STRING above. -end -item: Remark - Text= The "Title:" in the upper left corner of the GUI. -end -item: Remark - Text= Build Settings and Version Resource on step 6 (Finish) of the Installation Expert -end -item: Remark - Text= Be sure to select Steps->All or you may not see these! -end -item: Remark -end -item: Remark - Text=When the version of Tcl/Tk changes, the compiler vrbl -end -item: Remark - Text=_TCLDIR_ may also need to be changed. -end -item: Remark -end -item: Set Variable - Variable=APPTITLE - Value=Python %PYVER_STRING% -end -item: Remark - Text=PY_VERSION should be major.minor only; used to create the registry key; must match MS_DLL_ID in python_nt.rc -end -item: Set Variable - Variable=PY_VERSION - Value=%_PYMAJOR_%.%_PYMINOR_% -end -item: Remark - Text=GROUP is the Start menu group name; user can override. -end -item: Set Variable - Variable=GROUP - Value=Python %PY_VERSION% - Flags=10000000 -end -item: Remark - Text=MAINDIR is the app directory; user can override. -end -item: Set Variable - Variable=MAINDIR - Value=Python%_PYMAJOR_%%_PYMINOR_% -end -item: Remark -end -item: Set Variable - Variable=DOADMIN - Value=%_DOADMIN_% -end -item: Remark - Text=Give non-admin users a chance to abort. -end -item: Check Configuration - Flags=10011111 -end -item: Set Variable - Variable=DOADMIN - Value=0 -end -item: Display Message - Title=Doing non-admin install - Text=The current login does not have Administrator Privileges on this machine. Python will install its registry information into the per-user area only for the current login, instead of into the per-machine area for every account on this machine. Some advanced uses of Python may not work as a result (for example, running a Python script as a service). - Text= - Text=If this is not what you want, please click Cancel to abort this installation, log on as an Administrator, and start the installation again. - Flags=00001000 -end -item: End Block -end -item: Remark -end -item: Remark - Text=BEGIN WIZARD STUFF ----------------------------------------------------------------------------------------------------------------------------- -end -item: Remark - Text=Note from Tim: the "stop" on the next line is actually "pause". -end -item: Open/Close INSTALL.LOG - Flags=00000001 -end -item: Remark - Text=If the destination system does not have a writable Windows\System directory, system files will be written to the Windows\ directory -end -item: Check if File/Dir Exists - Pathname=%SYS% - Flags=10000100 -end -item: Set Variable - Variable=SYS - Value=%WIN% -end -item: End Block -end -item: Check Configuration - Flags=10111011 -end -item: Get Registry Key Value - Variable=COMMON - Key=SOFTWARE\Microsoft\Windows\CurrentVersion - Default=C:\Program Files\Common Files - Value Name=CommonFilesDir - Flags=00000100 -end -item: Get Registry Key Value - Variable=PROGRAM_FILES - Key=SOFTWARE\Microsoft\Windows\CurrentVersion - Default=C:\Program Files - Value Name=ProgramFilesDir - Flags=00000100 -end -item: Set Variable - Variable=EXPLORER - Value=1 -end -item: End Block -end -item: Remark - Text=Note from Tim: The Wizard hardcod "C:" at the start of the replacement text for MAINDIR. -end -item: Remark - Text=That's not appropriate if the system drive doesn't happen to be C:. -end -item: Remark - Text=I removed the "C:", and that did the right thing for two people who tested it on non-C: machines, -end -item: Remark - Text=but it's unclear whether it will always do the right thing. -end -item: Set Variable - Variable=MAINDIR - Value=\%MAINDIR% - Flags=00001100 -end -item: Remark - Text=BACKUP is the variable that holds the path that all backup files will be copied to when overwritten -end -item: Set Variable - Variable=BACKUP - Value=%MAINDIR%\BACKUP - Flags=10000000 -end -item: Remark - Text=DOBACKUP determines if a backup will be performed. The possible values are A (do backup) or B (do not do backup) -end -item: Set Variable - Variable=DOBACKUP - Value=A -end -item: Remark - Text=BRANDING determines if the installation will be branded with a name and company. By default, this is written to the INST directory (installation media). -end -item: Set Variable - Variable=BRANDING - Value=0 -end -item: If/While Statement - Variable=BRANDING - Value=1 -end -item: Read INI Value - Variable=NAME - Pathname=%INST%\CUSTDATA.INI - Section=Registration - Item=Name -end -item: Read INI Value - Variable=COMPANY - Pathname=%INST%\CUSTDATA.INI - Section=Registration - Item=Company -end -item: If/While Statement - Variable=NAME -end -item: Set Variable - Variable=DOBRAND - Value=1 -end -item: Get System Information - Variable=NAME - Flags=00000110 -end -item: Get System Information - Variable=COMPANY - Flags=00000111 -end -item: End Block -end -item: End Block -end -item: Remark - Text=END WIZARD STUFF ----------------------------------------------------------------------------------------------------------------------------- -end -item: Remark -end -item: Remark - Text=Set vrbls for the "Advanced Options" subdialog of Components. -end -item: Set Variable - Variable=SELECT_ADMIN - Value=A -end -item: If/While Statement - Variable=DOADMIN - Value=0 -end -item: Set Variable - Variable=SELECT_ADMIN - Value=B -end -item: End Block -end -item: Remark -end -item: Remark - Text=TASKS values: -end -item: Remark - Text=A: Register file extensions -end -item: Remark - Text=B: Create Start Menu shortcuts -end -item: Set Variable - Variable=TASKS - Value=AB -end -item: Remark -end -item: Remark - Text=COMPONENTS values: -end -item: Remark - Text=A: interpreter and libraries -end -item: Remark - Text=B: Tcl/Tk -end -item: Remark - Text=C: docs -end -item: Remark - Text=D: tools -end -item: Remark - Text=E: test suite -end -item: Set Variable - Variable=COMPONENTS - Value=ABCDE -end -item: Remark -end -item: Remark - Text=March thru the user GUI. -end -item: Wizard Block - Direction Variable=DIRECTION - Display Variable=DISPLAY - Bitmap Pathname=.\installer.bmp - X Position=9 - Y Position=10 - Filler Color=11173759 - Dialog=Select Destination Directory - Dialog=Backup Replaced Files - Dialog=Select Components - Dialog=Select Program Manager Group - Variable= - Variable= - Variable= - Variable=TASKS - Value= - Value= - Value= - Value=B - Compare=0 - Compare=0 - Compare=0 - Compare=3 - Flags=00000011 -end -item: If/While Statement - Variable=DISPLAY - Value=Start Installation -end -item: Set Variable - Variable=SUMMARY - Value=Install directory: %MAINDIR%%CRLF% -end -item: Remark -end -item: If/While Statement - Variable=SELECT_ADMIN - Value=A -end -item: Set Variable - Variable=SUMMARY - Value=%CRLF%Doing admin install.%CRLF% - Flags=00000001 -end -item: Else Statement -end -item: Set Variable - Variable=SUMMARY - Value=%CRLF%Doing non-admin install.%CRLF% - Flags=00000001 -end -item: End Block -end -item: Remark -end -item: If/While Statement - Variable=DOBACKUP - Value=A -end -item: Set Variable - Variable=SUMMARY - Value=%CRLF%Make backups, into %BACKUP%%CRLF% - Flags=00000001 -end -item: Else Statement -end -item: Set Variable - Variable=SUMMARY - Value=%CRLF%Don't make backups.%CRLF% - Flags=00000001 -end -item: End Block -end -item: Remark -end -item: Set Variable - Variable=SUMMARY - Value=%CRLF%Components:%CRLF% - Flags=00000001 -end -item: If/While Statement - Variable=COMPONENTS - Value=A - Flags=00000010 -end -item: Set Variable - Variable=SUMMARY - Value= Python interpreter and libraries%CRLF% - Flags=00000001 -end -item: End Block -end -item: If/While Statement - Variable=COMPONENTS - Value=B - Flags=00000010 -end -item: Set Variable - Variable=SUMMARY - Value= Tcl/Tk (Tkinter, IDLE, pydoc)%CRLF% - Flags=00000001 -end -item: End Block -end -item: If/While Statement - Variable=COMPONENTS - Value=C - Flags=00000010 -end -item: Set Variable - Variable=SUMMARY - Value= Python documentation%CRLF% - Flags=00000001 -end -item: End Block -end -item: If/While Statement - Variable=COMPONENTS - Value=D - Flags=00000010 -end -item: Set Variable - Variable=SUMMARY - Value= Tool and utility scripts%CRLF% - Flags=00000001 -end -item: End Block -end -item: If/While Statement - Variable=COMPONENTS - Value=E - Flags=00000010 -end -item: Set Variable - Variable=SUMMARY - Value= Python test suite%CRLF% - Flags=00000001 -end -item: End Block -end -item: Remark -end -item: If/While Statement - Variable=TASKS - Value=A - Flags=00000010 -end -item: Set Variable - Variable=SUMMARY - Value=%CRLF%Register file extensions.%CRLF% - Flags=00000001 -end -item: Else Statement -end -item: Set Variable - Variable=SUMMARY - Value=%CRLF%Don't register file extensions.%CRLF% - Flags=00000001 -end -item: End Block -end -item: Remark -end -item: If/While Statement - Variable=TASKS - Value=B - Flags=00000010 -end -item: Set Variable - Variable=SUMMARY - Value=%CRLF%Start Menu group: %GROUP%%CRLF% - Flags=00000001 -end -item: Else Statement -end -item: Set Variable - Variable=SUMMARY - Value=%CRLF%No Start Menu shortcuts.%CRLF% - Flags=00000001 -end -item: End Block -end -item: End Block -end -item: Remark -end -item: Custom Dialog Set - Name=Select Destination Directory - Display Variable=DISPLAY - item: Dialog - Title=%APPTITLE% Installation - Title French=Installation de %APPTITLE% - Title German=Installation von %APPTITLE% - Title Spanish=Instalaci?n de %APPTITLE% - Title Italian=Installazione di %APPTITLE% - Width=339 - Height=280 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=188 234 244 253 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suite > - Text German=&Weiter > - Text Spanish=&Siguiente > - Text Italian=&Avanti > - end - item: Push Button - Rectangle=264 234 320 253 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=&Cancel - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Static - Rectangle=10 225 320 226 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=108 11 323 33 - Create Flags=01010000000000000000000000000000 - Flags=0000000000000001 - Name=Times New Roman - Font Style=-24 0 0 0 700 255 0 0 0 3 2 1 18 - Text=Select Destination Directory - Text French=S?lectionner le r?pertoire de destination - Text German=Zielverzeichnis w?hlen - Text Spanish=Seleccione el directorio de destino - Text Italian=Selezionare Directory di destinazione - end - item: Listbox - Rectangle=108 58 321 219 - Variable=MAINDIR - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000100000010000000101000001 - Flags=0000110000001010 - Text=%MAINDIR% - Text= - end - item: Static - Rectangle=108 40 313 58 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000000000 - Text=Please select a directory for the %APPTITLE% files. - end - end - item: Dialog - Title=Select Destination Directory - Title French=S?lectionner le r?pertoire de destination - Title German=Zielverzeichnis w?hlen - Title Spanish=Seleccione el directorio de destino - Title Italian=Selezionare Directory di destinazione - Width=276 - Height=216 - Font Name=Helv - Font Size=8 - item: Listbox - Rectangle=6 6 204 186 - Variable=MAINDIR - Create Flags=01010000100000010000000101000000 - Flags=0000110000100010 - Text=%MAINDIR% - Text French=%MAINDIR% - Text German=%MAINDIR% - Text Spanish=%MAINDIR% - Text Italian=%MAINDIR% - end - item: Push Button - Rectangle=209 8 265 26 - Create Flags=01010000000000010000000000000001 - Text=OK - Text French=OK - Text German=OK - Text Spanish=Aceptar - Text Italian=OK - end - item: Push Button - Rectangle=209 31 265 50 - Variable=MAINDIR - Value=%MAINDIR_SAVE% - Create Flags=01010000000000010000000000000000 - Flags=0000000000000001 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Spanish=Cancelar - Text Italian=Annulla - end - end -end -item: Custom Dialog Set - Name=Backup Replaced Files - Display Variable=DISPLAY - item: Dialog - Title=%APPTITLE% Installation - Title French=Fichiers de Sauvegarde Remplac?s - Title German=Sicherungskopie von ersetzten Dateien erstellen - Title Portuguese=Ficheiros substitu?dos de seguran?a - Title Spanish=Copias de seguridad de los archivos reemplazados - Title Italian=Backup file sostituiti - Title Danish=Sikkerhedskopiering af erstattede filer - Title Dutch=Vervangen bestanden kopi?ren - Title Norwegian=Sikkerhetskopiere erstattede filer - Title Swedish=S?kerhetskopiera utbytta filer - Width=350 - Height=280 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=188 234 244 251 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suivant> - Text German=&Weiter> - Text Portuguese=&Pr?ximo> - Text Spanish=&Siguiente > - Text Italian=&Avanti > - Text Danish=&N?ste> - Text Dutch=&Volgende> - Text Norwegian=&Neste> - Text Swedish=&N?sta > - end - item: Push Button - Rectangle=131 234 188 251 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Text=< &Back - Text French=<&Retour - Text German=<&Zur?ck - Text Portuguese=<&Retornar - Text Spanish=<&Retroceder - Text Italian=< &Indietro - Text Danish=<&Tilbage - Text Dutch=<&Terug - Text Norwegian=<&Tilbake - Text Swedish=< &Tillbaka - end - item: Push Button - Rectangle=278 234 330 251 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Annuller - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=11 221 329 223 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=108 46 320 98 - Create Flags=01010000000000000000000000000000 - Text=This installation program can create backup copies of all files replaced during the installation. These files will be used when the software is uninstalled and a rollback is requested. If backup copies are not created, you will only be able to uninstall the software and not roll the system back to a previous state. - Text= - Text=Do you want to create backups of replaced files? - Text French=Le programme d'installation peut cr?er des copies de sauvegarde de tous les fichiers remplac?s pendant l'installation. Ces fichiers sont utilis?s au cas o? le logiciel est d?sinstall? et que l'on proc?de ? la reprise du syst?me. Si les copies de sauvegarde ne sont pas cr??es, on ne pourra que d?sinstaller le logiciel sans reprendre le syst?me ? un ?tat pr?c?dent. Voulez-vous cr?er une sauvegarde des fichiers remplac?s ? - Text German=Dieses Installationsprogramm kann Sicherungskopien von allen w?hrend der Installation ersetzten Dateien erstellen. Diese Dateien werden zur R?ckg?ngigmachung der Installation und bei Anforderung eines Rollbacks verwendet. Ohne Sicherungskopien ist nur eine R?ckg?ngigmachung der Installation m?glich, nicht aber ein Rollback des Systems. Sicherungskopien der ersetzten Dateien erstellen? - Text Portuguese=Este programa de instala??o pode criar c?pias de seguran?a de todos os ficheiros substitu?dos durante a instala??o. Estes ficheiros ser?o utilizados quando o programa for desinstalado e for requisitada uma retomada. Se as c?pias de seguran?a n?o forem criadas, s? poder? desinstalar o programa e n?o pode retomar um estado anterior do sistema. Deseja criar c?pias de seguran?a dos ficheiros substitu?dos? - Text Spanish=Este programa de instalaci?n puede crear copias de seguridad de todos los archivos reemplazados durante la instalaci?n. Estos archivos se utilizar?n cuando se desinstale el software y se solicite volver al estado anterior. Si no se crean copias de seguridad, ?nicamente podr? desinstalar el software y no podr? devolver el sistema al estado anterior. ?Desea crear archivos de seguridad de los archivos reemplazados? - Text Italian=Questo programma di installazione pu? creare copie di backup di tutti i file sostituiti durante l?installazione. Questi file saranno usati quando il software sar? disinstallato e sar? richiesto un ritorno allo stato precedente. Se non crei le copie di backup, potrai solo disinstallare il software, ma non potrai riportare il sistema allo stato precedente. Vuoi creare i file di backup dei file sostituiti? - Text Danish=Dette installationsprogram kan oprette sikkerhedskopier af alle filer, som erstattes under installationen. Disse filer benyttes, n?r softwaren fjernes, og den tidligere systemkonfiguration genetableres. Hvis der ikke oprettes sikkerhedskopier, kan du kun fjerne den installerede software og ikke genetablere den tidligere systemkonfiguration. Vil du oprette sikkerhedskopier af filer, som erstattes? - Text Dutch=Dit installatieprogramma kan kopie?n maken van alle bestanden die tijdens de installatie worden vervangen. Deze worden dan gebruikt als de software-installatie ongedaan wordt gemaakt en u het systeem wilt laten terugkeren naar de oorspronkelijke staat. Als er geen back-up kopie?n worden gemaakt, kunt u de software enkel verwijderen maar het systeem niet in de oorspronkelijke staat terugbrengen. Wilt u een back-up maken van de vervangen bestanden? - Text Norwegian=Dette installasjonsprogrammet kan lage sikkerhetskopier av alle filer som blir erstattet under installasjonen. Disse filene vil tas i bruk n?r programvaren er avinstallert og det er behov for tilbakestilling. Hvis det ikke er laget sikkerhetskopier, kan du kun avinstallere programvaren og ikke stille systemet tilbake til tidligere status. ?nsker du ? lage sikkerhetskopier av de filene som blir erstattet n?? - Text Swedish=Installationsprogrammet kan skapa s?kerhetskopior av alla filer som byts ut under installationen. Dessa filer kan sedan anv?ndas n?r programvaran avinstalleras och du beg?r rollback. Om du d? inte har n?gra s?kerhetskopior kan du bara avinstallera programvaran, inte ?terskapa systemet i dess tidigare skick. Vill du g?ra s?kerhetskopior av de ersatta filerna? - end - item: Radio Button - Rectangle=141 106 265 136 - Variable=DOBACKUP - Create Flags=01010000000000010000000000001001 - Text=&Yes, make backups - Text=N&o, do not make backups - Text= - Text French=&Oui - Text French=N&on - Text French= - Text German=&Ja - Text German=N&ein - Text German= - Text Portuguese=&Sim - Text Portuguese=N?&o - Text Portuguese= - Text Spanish=&S? - Text Spanish=N&o - Text Spanish= - Text Italian=&S? - Text Italian=N&o - Text Italian= - Text Danish=&Ja - Text Danish=&Nej - Text Danish= - Text Dutch=&Ja - Text Dutch=N&ee - Text Dutch= - Text Norwegian=&Ja - Text Norwegian=&Nei - Text Norwegian= - Text Swedish=&Ja - Text Swedish=N&ej - Text Swedish= - end - item: Static - Control Name=BACK2 - Rectangle=108 173 320 208 - Action=1 - Create Flags=01010000000000000000000000000111 - Text=Backup File Destination Directory - Text French=R?pertoire de destination des fichiers de sauvegarde - Text German=Zielverzeichnis f?r die Sicherungsdatei - Text Portuguese=Direct?rio de destino de ficheiro de seguran?a - Text Spanish=Directorio de Destino de los Archivos de Seguridad - Text Italian=Directory di destinazione dei file di backup - Text Danish=Destinationsbibliotek til sikkerhedskopier - Text Dutch=Doeldirectory backup-bestand - Text Norwegian=M?lkatalog for sikkerhetskopier - Text Swedish=Katalog f?r s?kerhetskopierade filer - end - item: Push Button - Control Name=BACK3 - Rectangle=265 185 318 203 - Variable=BACKUP_SAVE - Value=%BACKUP% - Destination Dialog=1 - Action=2 - Create Flags=01010000000000010000000000000000 - Text=B&rowse... - Text French=P&arcourir - Text German=B&l?ttern... - Text Portuguese=P&rocurar - Text Spanish=V&isualizar... - Text Italian=Sfoglia... - Text Danish=&Gennemse... - Text Dutch=B&laderen... - Text Norwegian=Bla igjennom - Text Swedish=&Bl?ddra - end - item: Static - Control Name=BACK4 - Rectangle=129 188 254 200 - Destination Dialog=2 - Create Flags=01010000000000000000000000000000 - Text=%BACKUP% - Text French=%BACKUP% - Text German=%BACKUP% - Text Portuguese=%BACKUP% - Text Spanish=%BACKUP% - Text Italian=%BACKUP% - Text Danish=%BACKUP% - Text Dutch=%BACKUP% - Text Norwegian=%BACKUP% - Text Swedish=%BACKUP% - end - item: Static - Rectangle=108 11 323 36 - Create Flags=01010000000000000000000000000000 - Flags=0000000000000001 - Name=Times New Roman - Font Style=-24 0 0 0 700 255 0 0 0 3 2 1 18 - Text=Backup Replaced Files - Text French=S?lectionner les composants - Text German=Komponenten ausw?hlen - Text Spanish=Seleccione componentes - Text Italian=Selezionare i componenti - end - item: If/While Statement - Variable=DOBACKUP - Value=B - end - item: Set Control Attribute - Control Name=BACK3 - Operation=1 - end - item: Set Control Attribute - Control Name=BACK4 - Operation=1 - end - item: Else Statement - end - item: Set Control Attribute - Control Name=BACK3 - end - item: Set Control Attribute - Control Name=BACK4 - end - item: End Block - end - end - item: Dialog - Title=Select Destination Directory - Title French=Choisissez le r?pertoire de destination - Title German=Zielverzeichnis w?hlen - Title Portuguese=Seleccionar Direct?rio de Destino - Title Spanish=Seleccione el Directorio de Destino - Title Italian=Seleziona Directory di destinazione - Title Danish=V?lg Destinationsbibliotek - Title Dutch=Kies Doeldirectory - Title Norwegian=Velg m?lkatalog - Title Swedish=V?lj destinationskalatog - Width=276 - Height=216 - Font Name=Helv - Font Size=8 - item: Listbox - Rectangle=6 3 200 186 - Variable=BACKUP - Create Flags=01010000100000010000000101000000 - Flags=0000110000100010 - Text=%BACKUP% - Text= - Text French=%BACKUP% - Text French= - Text German=%BACKUP% - Text German= - Text Portuguese=%BACKUP% - Text Portuguese= - Text Spanish=%BACKUP% - Text Spanish= - Text Italian=%BACKUP% - Text Italian= - Text Danish=%BACKUP% - Text Danish= - Text Dutch=%BACKUP% - Text Dutch= - Text Norwegian=%BACKUP% - Text Norwegian= - Text Swedish=%BACKUP% - Text Swedish= - end - item: Push Button - Rectangle=209 8 265 26 - Create Flags=01010000000000010000000000000001 - Text=OK - Text French=OK - Text German=OK - Text Portuguese=OK - Text Spanish=ACEPTAR - Text Italian=OK - Text Danish=OK - Text Dutch=OK - Text Norwegian=OK - Text Swedish=OK - end - item: Push Button - Rectangle=209 31 265 50 - Variable=BACKUP - Value=%BACKUP_SAVE% - Create Flags=01010000000000010000000000000000 - Flags=0000000000000001 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Slet - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - end -end -item: Custom Dialog Set - Name=Select Components - Display Variable=DISPLAY - item: Dialog - Title=%APPTITLE% Installation - Title French=Installation de %APPTITLE% - Title German=Installation von %APPTITLE% - Title Spanish=Instalaci?n de %APPTITLE% - Title Italian=Installazione di %APPTITLE% - Width=339 - Height=280 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=188 234 244 253 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suite > - Text German=&Weiter > - Text Spanish=&Siguiente > - Text Italian=&Avanti > - end - item: Push Button - Rectangle=131 234 188 253 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Text=< &Back - Text French=< &Retour - Text German=< &Zur?ck - Text Spanish=< &Atr?s - Text Italian=< &Indietro - end - item: Push Button - Rectangle=264 234 320 253 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=&Cancel - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Checkbox - Rectangle=108 66 313 156 - Variable=COMPONENTS - Create Flags=01010000000000010000000000000011 - Flags=0000000000000110 - Text=Python interpreter and libraries - Text=Tcl/Tk (Tkinter, IDLE, pydoc) - Text=Python HTML docs - Text=Python utility scripts (Tools/) - Text=Python test suite (Lib/test/) - Text= - Text French=Python interpreter, library and IDLE - Text French=Python HTML docs - Text French=Python utility scripts (Tools/) - Text French=Python test suite (Lib/test/) - Text French= - Text German=Python interpreter, library and IDLE - Text German=Python HTML docs - Text German=Python utility scripts (Tools/) - Text German=Python test suite (Lib/test/) - Text German= - Text Spanish=Python interpreter, library and IDLE - Text Spanish=Python HTML docs - Text Spanish=Python utility scripts (Tools/) - Text Spanish=Python test suite (Lib/test/) - Text Spanish= - Text Italian=Python interpreter, library and IDLE - Text Italian=Python HTML docs - Text Italian=Python utility scripts (Tools/) - Text Italian=Python test suite (Lib/test/) - Text Italian= - end - item: Static - Rectangle=108 45 320 63 - Create Flags=01010000000000000000000000000000 - Text=Choose which components to install by checking the boxes below. - Text French=Choisissez les composants que vous voulez installer en cochant les cases ci-dessous. - Text German=W?hlen Sie die zu installierenden Komponenten, indem Sie in die entsprechenden K?stchen klicken. - Text Spanish=Elija los componentes que desee instalar marcando los cuadros de abajo. - Text Italian=Scegliere quali componenti installare selezionando le caselle sottostanti. - end - item: Push Button - Rectangle=188 203 269 220 - Destination Dialog=1 - Action=2 - Enabled Color=00000000000000000000000011111111 - Create Flags=01010000000000010000000000000000 - Text=Advanced Options ... - end - item: Static - Rectangle=10 225 320 226 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=108 10 323 43 - Create Flags=01010000000000000000000000000000 - Flags=0000000000000001 - Name=Times New Roman - Font Style=-24 0 0 0 700 255 0 0 0 3 2 1 18 - Text=Select Components - Text French=S?lectionner les composants - Text German=Komponenten ausw?hlen - Text Spanish=Seleccione componentes - Text Italian=Selezionare i componenti - end - item: Static - Rectangle=251 180 311 193 - Variable=COMPONENTS - Value=MAINDIR - Create Flags=01010000000000000000000000000010 - end - item: Static - Rectangle=251 168 311 179 - Variable=COMPONENTS - Create Flags=01010000000000000000000000000010 - end - item: Static - Rectangle=123 168 234 181 - Create Flags=01010000000000000000000000000000 - Text=Disk Space Required: - Text French=Espace disque requis : - Text German=Notwendiger Speicherplatz: - Text Spanish=Espacio requerido en el disco: - Text Italian=Spazio su disco necessario: - end - item: Static - Rectangle=123 180 234 193 - Create Flags=01010000000000000000000000000000 - Text=Disk Space Remaining: - Text French=Espace disque disponible : - Text German=Verbleibender Speicherplatz: - Text Spanish=Espacio en disco disponible: - Text Italian=Spazio su disco disponibile: - end - item: Static - Rectangle=108 158 320 196 - Action=1 - Create Flags=01010000000000000000000000000111 - end - item: If/While Statement - Variable=DLG_EVENT_TYPE - Value=VERIFY - end - item: Remark - Text=If they're installing Tcl/Tk, Tools, or the test suite, doesn't make much sense unless they're installing Python too. - end - item: If/While Statement - Variable=COMPONENTS - Value=BDE - Flags=00001010 - end - item: If/While Statement - Variable=COMPONENTS - Value=A - Flags=00000011 - end - item: Display Message - Title=Are you sure? - Text=Installing Tcl/Tk, Tools or the test suite doesn't make much sense unless you install the Python interpreter and libraries too. - Text= - Text=Click Yes if that's really what you want. - Flags=00101101 - end - item: Remark - Text=Nothing -- just proceed to the next dialog. - end - item: Else Statement - end - item: Remark - Text=Return to the dialog. - end - item: Set Variable - Variable=DLG_EVENT_TYPE - end - item: End Block - end - item: End Block - end - item: End Block - end - item: End Block - end - end - item: Dialog - Title=Advanced Options - Width=339 - Height=213 - Font Name=Helv - Font Size=8 - item: Radio Button - Control Name=ADMIN2 - Rectangle=11 46 90 76 - Variable=SELECT_ADMIN - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000010000000000001001 - Text=Admin install - Text=Non-Admin installl - Text= - end - item: Push Button - Rectangle=188 170 244 189 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=OK - Text French=&Suite > - Text German=&Weiter > - Text Spanish=&Siguiente > - Text Italian=&Avanti > - end - item: Static - Rectangle=5 3 326 83 - Action=1 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000000111 - end - item: Static - Control Name=ADMIN1 - Rectangle=11 11 321 45 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000000000 - Text=By default, the install records settings in the per-machine area of the registry (HKLM), and installs the Python and C runtime DLLs to %SYS32%. Choose "Non-Admin install" if you would prefer settings made in the per-user registry (HKCU), and DLLs installed in %MAINDIR%. - end - item: Static - Rectangle=5 90 326 157 - Action=1 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000000111 - end - item: Checkbox - Rectangle=11 121 243 151 - Variable=TASKS - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000010000000000000011 - Text=Register file extensions (.py, .pyw, .pyc, .pyo) - Text=Create Start Menu shortcuts - Text= - end - item: Static - Rectangle=11 103 320 121 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000000000 - Text=Choose tasks to perform by checking the boxes below. - end - item: If/While Statement - Variable=DLG_EVENT_TYPE - Value=INIT - end - item: If/While Statement - Variable=DOADMIN - Value=1 - end - item: Set Control Attribute - Control Name=ADMIN2 - end - item: Else Statement - end - item: Set Control Text - Control Name=ADMIN1 - Control Text=This section is available only if logged in to an account with Administrator privileges. - end - item: Set Control Attribute - Control Name=ADMIN2 - Operation=1 - end - item: End Block - end - item: End Block - end - end -end -item: Custom Dialog Set - Name=Select Program Manager Group - Display Variable=DISPLAY - item: Dialog - Title=%APPTITLE% Installation - Title French=Installation de %APPTITLE% - Title German=Installation von %APPTITLE% - Title Spanish=Instalaci?n de %APPTITLE% - Title Italian=Installazione di %APPTITLE% - Width=339 - Height=280 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=188 234 244 253 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suite > - Text German=&Weiter > - Text Spanish=&Siguiente > - Text Italian=&Avanti > - end - item: Push Button - Rectangle=131 234 188 253 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Flags=0000000000000001 - Text=< &Back - Text French=< &Retour - Text German=< &Zur?ck - Text Spanish=< &Atr?s - Text Italian=< &Indietro - end - item: Push Button - Rectangle=264 234 320 253 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=&Cancel - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Static - Rectangle=10 225 320 226 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=108 10 323 53 - Create Flags=01010000000000000000000000000000 - Flags=0000000000000001 - Name=Times New Roman - Font Style=-24 0 0 0 700 255 0 0 0 3 2 1 18 - Text=Select Start Menu Group - Text French=S?lectionner le groupe du Gestionnaire de programme - Text German=Bestimmung der Programm-Managergruppe - Text Spanish=Seleccione grupo del Administrador de programas - Text Italian=Selezionare il gruppo ProgMan - end - item: Static - Rectangle=108 35 320 65 - Create Flags=01010000000000000000000000000000 - Text=Enter the name of the Start Menu program group to which to add the %APPTITLE% icons: - Text French=Entrez le nom du groupe du Gestionnaire de programme dans lequel vous souhaitez ajouter les ic?nes de %APPTITLE% : - Text German=Geben Sie den Namen der Programmgruppe ein, der das Symbol %APPTITLE% hinzugef?gt werden soll: - Text Spanish=Escriba el nombre del grupo del Administrador de programas en el que desea agregar los iconos de %APPTITLE%: - Text Italian=Inserire il nome del gruppo Program Manager per aggiungere le icone %APPTITLE% a: - end - item: Combobox - Rectangle=108 56 320 219 - Variable=GROUP - Create Flags=01010000001000010000001100000001 - Flags=0000000000000001 - Text=%GROUP% - Text= - Text French=%GROUP% - Text German=%GROUP% - Text Spanish=%GROUP% - Text Italian=%GROUP% - end - end -end -item: Custom Dialog Set - Name=Start Installation - Display Variable=DISPLAY - item: Dialog - Title=%APPTITLE% Installation - Title French=Installation de %APPTITLE% - Title German=Installation von %APPTITLE% - Title Spanish=Instalaci?n de %APPTITLE% - Title Italian=Installazione di %APPTITLE% - Width=339 - Height=280 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=188 234 244 253 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suite > - Text German=&Weiter > - Text Spanish=&Siguiente > - Text Italian=&Avanti > - end - item: Push Button - Rectangle=131 234 188 253 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Text=< &Back - Text French=< &Retour - Text German=< &Zur?ck - Text Spanish=< &Atr?s - Text Italian=< &Indietro - end - item: Push Button - Rectangle=264 234 320 253 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=&Cancel - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Static - Rectangle=10 225 320 226 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=108 10 323 53 - Create Flags=01010000000000000000000000000000 - Flags=0000000000000001 - Name=Times New Roman - Font Style=-24 0 0 0 700 255 0 0 0 3 2 1 18 - Text=Ready to Install! - Text French=Pr?t ? installer ! - Text German=Installationsbereit! - Text Spanish=?Preparado para la instalaci?n! - Text Italian=Pronto per l'installazione! - end - item: Static - Rectangle=108 40 320 62 - Create Flags=01010000000000000000000000000000 - Text=Click the Next button to install %APPTITLE%, or the Back button to change choices: - Text French=Vous ?tes maintenant pr?t ? installer les fichiers %APPTITLE%. - Text French= - Text French=Cliquez sur le bouton Suite pour commencer l'installation ou sur le bouton Retour pour entrer les informations d'installation ? nouveau. - Text German=Sie k?nnen %APPTITLE% nun installieren. - Text German= - Text German=Klicken Sie auf "Weiter", um mit der Installation zu beginnen. Klicken Sie auf "Zur?ck", um die Installationsinformationen neu einzugeben. - Text Spanish=Ya est? listo para instalar %APPTITLE%. - Text Spanish= - Text Spanish=Presione el bot?n Siguiente para comenzar la instalaci?n o presione Atr?s para volver a ingresar la informaci?n para la instalaci?n. - Text Italian=Ora ? possibile installare %APPTITLE%. - Text Italian= - Text Italian=Premere il pulsante Avanti per avviare l'installazione o il pulsante Indietro per reinserire le informazioni di installazione. - end - item: Editbox - Rectangle=108 66 324 219 - Help Context=16711681 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000100000000001100011000100 - Text=%SUMMARY% - end - end -end -item: Remark -end -item: If/While Statement - Variable=DISPLAY - Value=Select Destination Directory -end -item: Remark - Text=User may have changed MAINDIR, so reset BACKUP to match. -end -item: Set Variable - Variable=BACKUP - Value=%MAINDIR%\BACKUP -end -item: End Block -end -item: Remark -end -item: End Block -end -item: Remark -end -item: Remark - Text=BEGIN WIZARD STUFF ----------------------------------------------------------------------------------------------------------------------------- -end -item: Remark - Text=When the BACKUP feature is enabled, the BACKUPDIR is initialized -end -item: If/While Statement - Variable=DOBACKUP - Value=A -end -item: Set Variable - Variable=BACKUPDIR - Value=%BACKUP% -end -item: End Block -end -item: Remark - Text=The BRANDING information is written to the INI file on the installation media. -end -item: If/While Statement - Variable=BRANDING - Value=1 -end -item: If/While Statement - Variable=DOBRAND - Value=1 -end -item: Edit INI File - Pathname=%INST%\CUSTDATA.INI - Settings=[Registration] - Settings=NAME=%NAME% - Settings=COMPANY=%COMPANY% - Settings= -end -item: End Block -end -item: End Block -end -item: Remark - Text=Begin writing to the INSTALL.LOG -end -item: Open/Close INSTALL.LOG -end -item: Remark - Text=Check free disk space calculates free disk space as well as component sizes. -end -item: Remark - Text=It should be located before all Install File actions. -end -item: Check Disk Space - Component=COMPONENTS -end -item: Remark - Text=This include script allows uninstall support -end -item: Remark - Text=Note from Tim: this is our own Uninstal.wse, a copy of Wise's except -end -item: Remark - Text=it writes to HKCU (instead of HKLM) if the user doesn't have admin privs. -end -item: Include Script - Pathname=.\Uninstal.wse -end -item: Remark - Text=Note from Tim: these seeming no-ops actually convert to short filenames. -end -item: Set Variable - Variable=COMMON - Value=%COMMON% - Flags=00010100 -end -item: Set Variable - Variable=MAINDIR - Value=%MAINDIR% - Flags=00010100 -end -item: Remark - Text=This IF/THEN/ELSE reads the correct registry entries for shortcut/icon placement -end -item: Check Configuration - Flags=10111011 -end -item: Get Registry Key Value - Variable=STARTUPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%WIN%\Start Menu\Programs\StartUp - Value Name=StartUp - Flags=00000010 -end -item: Get Registry Key Value - Variable=DESKTOPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%WIN%\Desktop - Value Name=Desktop - Flags=00000010 -end -item: Get Registry Key Value - Variable=STARTMENUDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%WIN%\Start Menu - Value Name=Start Menu - Flags=00000010 -end -item: Get Registry Key Value - Variable=GROUPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%WIN%\Start Menu\Programs - Value Name=Programs - Flags=00000010 -end -item: Get Registry Key Value - Variable=CSTARTUPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%STARTUPDIR% - Value Name=Common Startup - Flags=00000100 -end -item: Get Registry Key Value - Variable=CDESKTOPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%DESKTOPDIR% - Value Name=Common Desktop - Flags=00000100 -end -item: Get Registry Key Value - Variable=CSTARTMENUDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%STARTMENUDIR% - Value Name=Common Start Menu - Flags=00000100 -end -item: Get Registry Key Value - Variable=CGROUPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%GROUPDIR% - Value Name=Common Programs - Flags=00000100 -end -item: Else Statement -end -item: Remark - Text=Note from Tim: the Wizard left this block empty! -end -item: Remark - Text=Perhaps it's only relevant on Windows 3.1. -end -item: End Block -end -item: Remark - Text=END WIZARD STUFF ----------------------------------------------------------------------------------------------------------------------------- -end -item: Remark -end -item: If/While Statement - Variable=SELECT_ADMIN - Value=B -end -item: Remark - Text=The user chose a non-admin install in "Advanced Options". -end -item: Remark - Text=This should come after the include of Uninstal.wse above, because -end -item: Remark - Text=writing uninstall info to HKCU is ineffective except under Win2K. -end -item: Set Variable - Variable=DOADMIN - Value=0 -end -item: End Block -end -item: Remark -end -item: Set Variable - Variable=CGROUP_SAVE - Value=%GROUP% -end -item: If/While Statement - Variable=TASKS - Value=B - Flags=00000010 -end -item: If/While Statement - Variable=DOADMIN - Value=1 -end -item: Set Variable - Variable=GROUP - Value=%CGROUPDIR%\%GROUP% -end -item: Else Statement -end -item: Set Variable - Variable=GROUP - Value=%GROUPDIR%\%GROUP% -end -item: End Block -end -item: End Block -end -item: Remark -end -item: Remark - Text=Long section to install files. -end -item: Remark -end -item: If/While Statement - Variable=DOADMIN - Value=1 -end -item: Set Variable - Variable=DLLDEST - Value=%SYS32% -end -item: Else Statement -end -item: Set Variable - Variable=DLLDEST - Value=%MAINDIR% -end -item: End Block -end -item: Remark -end -item: Remark - Text=Install the license even if they deselect everything . -end -item: Install File - Source=..\license - Destination=%MAINDIR%\LICENSE.txt - Flags=0000000000000010 -end -item: Install File - Source=..\readme - Destination=%MAINDIR%\README.txt - Flags=0000000000000010 -end -item: Install File - Source=..\misc\news - Destination=%MAINDIR%\NEWS.txt - Flags=0000000000000010 -end -item: Remark - Text=Icons -- always install so that the uninstaller can use them for its own display. -end -item: Install File - Source=..\pc\pycon.ico - Destination=%MAINDIR%\pycon.ico - Flags=0000000010000010 -end -item: Install File - Source=..\pc\pyc.ico - Destination=%MAINDIR%\pyc.ico - Flags=0000000010000010 -end -item: Install File - Source=..\pc\py.ico - Destination=%MAINDIR%\py.ico - Flags=0000000010000010 -end -item: Remark -end -item: Remark - Text=These arrange to (recursively!) delete all .pyc and .pyo files at uninstall time. -end -item: Remark - Text=This "does the right thing": any directories left empty at the end are removed. -end -item: Add Text to INSTALL.LOG - Text=File Tree: %MAINDIR%\*.pyc -end -item: Add Text to INSTALL.LOG - Text=File Tree: %MAINDIR%\*.pyo -end -item: Remark -end -item: Remark - Text=A: interpreter and libraries -end -item: If/While Statement - Variable=COMPONENTS - Value=A - Flags=00000010 -end -item: Remark - Text=Executables -end -item: Install File - Source=.\python.exe - Destination=%MAINDIR%\python.exe - Flags=0000000000000010 -end -item: Install File - Source=.\pythonw.exe - Destination=%MAINDIR%\pythonw.exe - Flags=0000000000000010 -end -item: Install File - Source=.\w9xpopen.exe - Destination=%MAINDIR%\w9xpopen.exe - Flags=0000000000000010 -end -item: Remark -end -item: Remark - Text=Extension module DLLs (.pyd); keep in synch with libs directory next -end -item: Install File - Source=.\_winreg.pyd - Destination=%MAINDIR%\DLLs\_winreg.pyd - Description=Extension modules - Flags=0000000000000010 -end -item: Install File - Source=.\_csv.pyd - Destination=%MAINDIR%\DLLs\_csv.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\_sre.pyd - Destination=%MAINDIR%\DLLs\_sre.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\_ssl.pyd - Destination=%MAINDIR%\DLLs\_ssl.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\_symtable.pyd - Destination=%MAINDIR%\DLLs\_symtable.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\_testcapi.pyd - Destination=%MAINDIR%\DLLs\_testcapi.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\_tkinter.pyd - Destination=%MAINDIR%\DLLs\_tkinter.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\_socket.pyd - Destination=%MAINDIR%\DLLs\_socket.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\_bsddb.pyd - Destination=%MAINDIR%\DLLs\_bsddb.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\bz2.pyd - Destination=%MAINDIR%\DLLs\bz2.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\datetime.pyd - Destination=%MAINDIR%\DLLs\datetime.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\mmap.pyd - Destination=%MAINDIR%\DLLs\mmap.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\parser.pyd - Destination=%MAINDIR%\DLLs\parser.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\pyexpat.pyd - Destination=%MAINDIR%\DLLs\pyexpat.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\select.pyd - Destination=%MAINDIR%\DLLs\select.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\unicodedata.pyd - Destination=%MAINDIR%\DLLs\unicodedata.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\winsound.pyd - Destination=%MAINDIR%\DLLs\winsound.pyd - Flags=0000000000000010 -end -item: Install File - Source=.\zlib.pyd - Destination=%MAINDIR%\DLLs\zlib.pyd - Flags=0000000000000010 -end -item: Remark -end -item: Remark - Text=Link libraries (.lib); keep in synch with DLLs above, except that the Python lib lives here. -end -item: Install File - Source=.\_winreg.lib - Destination=%MAINDIR%\libs\_winreg.lib - Description=Link library files - Flags=0000000000000010 -end -item: Install File - Source=.\_csv.lib - Destination=%MAINDIR%\libs\_csv.lib - Flags=0000000000000010 -end -item: Install File - Source=.\_sre.lib - Destination=%MAINDIR%\libs\_sre.lib - Flags=0000000000000010 -end -item: Install File - Source=.\_ssl.lib - Destination=%MAINDIR%\libs\_ssl.lib - Flags=0000000000000010 -end -item: Install File - Source=.\_symtable.lib - Destination=%MAINDIR%\libs\_symtable.lib - Flags=0000000000000010 -end -item: Install File - Source=.\_testcapi.lib - Destination=%MAINDIR%\libs\_testcapi.lib - Flags=0000000000000010 -end -item: Install File - Source=.\_tkinter.lib - Destination=%MAINDIR%\libs\_tkinter.lib - Description=Extension modules - Flags=0000000000000010 -end -item: Install File - Source=.\_socket.lib - Destination=%MAINDIR%\libs\_socket.lib - Flags=0000000000000010 -end -item: Install File - Source=.\_bsddb.lib - Destination=%MAINDIR%\libs\_bsddb.lib - Flags=0000000000000010 -end -item: Install File - Source=.\bz2.lib - Destination=%MAINDIR%\libs\bz2.lib - Flags=0000000000000010 -end -item: Install File - Source=.\datetime.lib - Destination=%MAINDIR%\libs\datetime.lib - Flags=0000000000000010 -end -item: Install File - Source=.\mmap.lib - Destination=%MAINDIR%\libs\mmap.lib - Flags=0000000000000010 -end -item: Install File - Source=.\parser.lib - Destination=%MAINDIR%\libs\parser.lib - Flags=0000000000000010 -end -item: Install File - Source=.\pyexpat.lib - Destination=%MAINDIR%\libs\pyexpat.lib - Flags=0000000000000010 -end -item: Install File - Source=.\select.lib - Destination=%MAINDIR%\libs\select.lib - Flags=0000000000000010 -end -item: Install File - Source=.\unicodedata.lib - Destination=%MAINDIR%\libs\unicodedata.lib - Flags=0000000000000010 -end -item: Install File - Source=.\winsound.lib - Destination=%MAINDIR%\libs\winsound.lib - Flags=0000000000000010 -end -item: Install File - Source=.\zlib.lib - Destination=%MAINDIR%\libs\zlib.lib - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=.\python%_pymajor_%%_pyminor_%.lib - Destination=%MAINDIR%\libs\python%_PYMAJOR_%%_PYMINOR_%.lib - Flags=0000000000000010 -end -item: Remark -end -item: Remark - Text=Main Python DLL -end -item: Remark - Text=Tell Wise it's OK to delete the Python DLL at uninstall time, -end -item: Remark - Text=despite that we (may) write it into a system directory. -end -item: Add Text to INSTALL.LOG - Text=Non-System File: -end -item: Install File - Source=.\python%_pymajor_%%_pyminor_%.dll - Destination=%DLLDEST%\python%_PYMAJOR_%%_PYMINOR_%.dll - Flags=0000000000000010 -end -item: Remark -end -item: Remark - Text=Libraries (Lib/) -end -item: Install File - Source=..\lib\*.py - Destination=%MAINDIR%\Lib - Description=Library Modules - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\bsddb\*.py - Destination=%MAINDIR%\Lib\bsddb - Description=Berkeley database package - Flags=0000000100000010 -end -item: Remark -end -item: Install File - Source=..\lib\compiler\*.py - Destination=%MAINDIR%\Lib\compiler - Description=Python compiler written in Python - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\distutils\*.py - Destination=%MAINDIR%\Lib\distutils - Description=Distribution utility modules - Flags=0000000000000010 -end -item: Install File - Source=..\lib\distutils\readme - Destination=%MAINDIR%\Lib\distutils\README.txt - Flags=0000000000000010 -end -item: Install File - Source=..\lib\distutils\command\*.py - Destination=%MAINDIR%\Lib\distutils\command - Flags=0000000000000010 -end -item: Install File - Source=..\lib\distutils\command\wininst.exe - Destination=%MAINDIR%\Lib\distutils\command\wininst.exe - Flags=0000000000000010 -end -item: Install File - Source=..\lib\distutils\command\command_template - Destination=%MAINDIR%\Lib\distutils\command\command_template - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\email\*.py - Destination=%MAINDIR%\Lib\email - Description=Library email package - Flags=0000000000000010 -end -item: Install File - Source=..\lib\email\test\*.py - Destination=%MAINDIR%\Lib\email\test - Description=email tests - Flags=0000000000000010 -end -item: Install File - Source=..\lib\email\test\data\*.txt - Destination=%MAINDIR%\Lib\email\test\data - Description=email test data - Flags=0000000000000010 -end -item: Install File - Source=..\lib\email\test\data\*.gif - Destination=%MAINDIR%\Lib\email\test\data - Description=email test data - Flags=0000000000000010 -end -item: Install File - Source=..\lib\email\test\data\*.au - Destination=%MAINDIR%\Lib\email\test\data - Description=email test data - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\encodings\*.py - Destination=%MAINDIR%\Lib\encodings - Description=Unicode encoding tables - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\hotshot\*.py - Destination=%MAINDIR%\Lib\hotshot - Description=Fast Python profiler - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\lib-old\*.py - Destination=%MAINDIR%\Lib\lib-old - Description=Obsolete modules - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\lib-tk\*.py - Destination=%MAINDIR%\Lib\lib-tk - Description=Tkinter related library modules - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\logging\*.py - Destination=%MAINDIR%\Lib\logging - Description=Logging package - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\site-packages\readme - Destination=%MAINDIR%\Lib\site-packages\README.txt - Description=Site packages - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\xml\*.py - Destination=%MAINDIR%\Lib\xml - Description=XML support packages - Flags=0000000000000010 -end -item: Install File - Source=..\lib\xml\dom\*.py - Destination=%MAINDIR%\Lib\xml\dom - Flags=0000000000000010 -end -item: Install File - Source=..\lib\xml\parsers\*.py - Destination=%MAINDIR%\Lib\xml\parsers - Flags=0000000000000010 -end -item: Install File - Source=..\lib\xml\sax\*.py - Destination=%MAINDIR%\Lib\xml\sax - Flags=0000000000000010 -end -item: Remark -end -item: Remark - Text=C Include files -end -item: Install File - Source=..\include\*.h - Destination=%MAINDIR%\include - Description=Header files - Flags=0000000000000010 -end -item: Install File - Source=..\pc\pyconfig.h - Destination=%MAINDIR%\include\pyconfig.h - Description=Header files (pyconfig.h) - Flags=0000000000000010 -end -item: Remark -end -item: Remark - Text=Microsoft C runtime libraries -end -item: Install File - Source=%_SYS_%\MSVCIRT.DLL - Destination=%DLLDEST%\MSVCIRT.DLL - Description=Visual C++ Runtime DLLs - Flags=0000011000010011 -end -item: Install File - Source=%_SYS_%\MSVCRT.DLL - Destination=%DLLDEST%\MSVCRT.DLL - Description=Visual C++ Runtime DLLs - Flags=0000011000010011 -end -item: End Block -end -item: Remark -end -item: Remark - Text=B: Tcl/Tk (Tkinter, IDLE, pydoc) -end -item: If/While Statement - Variable=COMPONENTS - Value=B - Flags=00000010 -end -item: Remark - Text=Tcl/Tk -end -item: Install File - Source=..\..\%_tcldir_%\bin\*.dll - Destination=%MAINDIR%\DLLs - Description=Tcl/Tk binaries and libraries - Flags=0000000000000010 -end -item: Install File - Source=..\..\%_tcldir_%\lib\*.* - Destination=%MAINDIR%\tcl - Description=Tcl/Tk binaries and libraries - Flags=0000000100000010 -end -item: Remark -end -item: Remark - Text=IDLE -end -item: Install File - Source=..\Lib\idlelib\*.py - Destination=%MAINDIR%\Lib\idlelib - Description=Integrated DeveLopment Environment for Python - Flags=0000000000000010 -end -item: Install File - Source=..\Lib\idlelib\*.txt - Destination=%MAINDIR%\Lib\idlelib - Description=Integrated DeveLopment Environment for Python - Flags=0000000000000010 -end -item: Install File - Source=..\Lib\idlelib\*.def - Destination=%MAINDIR%\Lib\idlelib - Description=Integrated DeveLopment Environment for Python - Flags=0000000000000010 -end -item: Install File - Source=..\Lib\idlelib\Icons\* - Destination=%MAINDIR%\Lib\idlelib\Icons - Description=Integrated DeveLopment Environment for Python - Flags=0000000000000010 -end -item: Install File - Source=..\Tools\scripts\idle - Destination=%MAINDIR%\Lib\idlelib\idle.pyw - Description=IDLE bootstrap script - Flags=0000000000000010 -end -item: Remark -end -item: Remark - Text=Windows pydoc driver -end -item: Install File - Source=..\tools\scripts\*.pyw - Destination=%MAINDIR%\Tools\Scripts - Description=Windows pydoc driver - Flags=0000000000000010 -end -item: End Block -end -item: Remark -end -item: Remark - Text=C: docs -end -item: If/While Statement - Variable=COMPONENTS - Value=C - Flags=00000010 -end -item: Install File - Source=%_DOC_%\*.* - Destination=%MAINDIR%\Doc - Description=Python Documentation (HTML) - Flags=0000000100000010 -end -item: End Block -end -item: Remark -end -item: Remark - Text=D: tools -end -item: If/While Statement - Variable=COMPONENTS - Value=D - Flags=00000010 -end -item: Install File - Source=..\tools\scripts\*.py - Destination=%MAINDIR%\Tools\Scripts - Description=Utility Scripts - Flags=0000000000000010 -end -item: Install File - Source=..\tools\scripts\*.doc - Destination=%MAINDIR%\Tools\Scripts - Description=Utility Scripts - Flags=0000000000000010 -end -item: Install File - Source=..\tools\scripts\readme - Destination=%MAINDIR%\Tools\Scripts\README.txt - Description=Utility Scripts - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\tools\webchecker\*.py - Destination=%MAINDIR%\Tools\webchecker - Description=Web checker tool - Flags=0000000000000010 -end -item: Install File - Source=..\tools\webchecker\readme - Destination=%MAINDIR%\Tools\webchecker\README.txt - Description=Web checker tool - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\tools\versioncheck\*.py - Destination=%MAINDIR%\Tools\versioncheck - Description=Version checker tool - Flags=0000000000000010 -end -item: Install File - Source=..\tools\versioncheck\readme - Destination=%MAINDIR%\Tools\versioncheck\README.txt - Description=Version checker tool - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\tools\pynche\*.py - Destination=%MAINDIR%\Tools\pynche - Description=pynche color editor - Flags=0000000000000010 -end -item: Install File - Source=..\tools\pynche\*.txt - Destination=%MAINDIR%\Tools\pynche - Description=pynche color editor - Flags=0000000000000010 -end -item: Install File - Source=..\tools\pynche\x\*.txt - Destination=%MAINDIR%\Tools\pynche\X - Description=pynche color editor - X files - Flags=0000000000000010 -end -item: Install File - Source=..\tools\pynche\readme - Destination=%MAINDIR%\Tools\pynche\README.txt - Description=pynche color editor - README - Flags=0000000100000010 -end -item: Install File - Source=..\tools\pynche\pynche - Destination=%MAINDIR%\Tools\pynche\pynche.py - Description=pynche color editor - main - Flags=0000000100000010 -end -item: Install File - Source=..\tools\pynche\pynche.pyw - Destination=%MAINDIR%\Tools\pynche\pynche.pyw - Description=pynche color editor - noconsole main - Flags=0000000100000010 -end -item: Remark -end -item: Install File - Source=..\tools\i18n\*.py - Destination=%MAINDIR%\Tools\i18n - Description=Internationalization helpers - Flags=0000000000000010 -end -item: End Block -end -item: Remark -end -item: Remark - Text=E: test suite -end -item: If/While Statement - Variable=COMPONENTS - Value=E - Flags=00000010 -end -item: Install File - Source=..\lib\test\audiotest.au - Destination=%MAINDIR%\Lib\test\audiotest.au - Description=Python Test files - Flags=0000000000000010 -end -item: Install File - Source=..\lib\test\*.uue - Destination=%MAINDIR%\Lib\test - Description=Python Test files - Flags=0000000000000010 -end -item: Install File - Source=..\lib\test\*.py - Destination=%MAINDIR%\Lib\test - Description=Python Test files - Flags=0000000000000010 -end -item: Install File - Source=..\lib\test\*.xml - Destination=%MAINDIR%\Lib\test - Description=Python Test files - Flags=0000000000000010 -end -item: Install File - Source=..\lib\test\*.out - Destination=%MAINDIR%\Lib\test - Description=Python Test files - Flags=0000000000000010 -end -item: Install File - Source=..\lib\test\*.bz2 - Destination=%MAINDIR%\Lib\test - Description=Python Test files - Flags=0000000000000010 -end -item: Install File - Source=..\lib\test\*.tar - Destination=%MAINDIR%\Lib\test - Description=Python Test files - Flags=0000000000000010 -end -item: Install File - Source=..\lib\test\*.gz - Destination=%MAINDIR%\Lib\test - Description=Python Test files - Flags=0000000000000010 -end -item: Install File - Source=..\lib\test\*.txt - Destination=%MAINDIR%\Lib\test - Description=Python Test files - Flags=0000000000000010 -end -item: Remark -end -item: Install File - Source=..\lib\test\output\*.* - Destination=%MAINDIR%\Lib\test\output - Description=Python Test output files - Flags=0000000000000010 -end -item: End Block -end -item: Remark -end -item: Remark - Text=DONE with file copying. -end -item: Remark - Text=The rest is registry and Start Menu fiddling. -end -item: Remark -end -item: If/While Statement - Variable=COMPONENTS - Value=A - Flags=00000010 -end -item: If/While Statement - Variable=TASKS - Value=A - Flags=00000010 -end -item: Remark - Text=Register file extensions. As usual, Admin privs get in the way, but with a twist: -end -item: Remark - Text=You don't need admin privs to write to HKEY_CLASSES_ROOT *except* under Win2K. -end -item: Remark - Text=On Win2K, a user without Admin privs has to register extensions under HKCU\Software\CLASSES instead. -end -item: Remark - Text=But while you can *do* that under other flavors of Windows too, it has no useful effect except in Win2K. -end -item: Set Variable - Variable=USE_HKCR - Value=1 -end -item: Check Configuration - Flags=11110010 -end -item: If/While Statement - Variable=DOADMIN - Value=0 -end -item: Set Variable - Variable=USE_HKCR - Value=0 -end -item: End Block -end -item: End Block -end -item: If/While Statement - Variable=USE_HKCR - Value=1 -end -item: Remark - Text=File types. -end -item: Edit Registry - Total Keys=1 - Key=Python.File - New Value=Python File -end -item: Edit Registry - Total Keys=1 - Key=Python.File\shell\open\command - New Value=%MAINDIR%\python.exe "%%1" %%* -end -item: Edit Registry - Total Keys=1 - Key=Python.File\DefaultIcon - New Value=%MAINDIR%\Py.ico -end -item: Remark -end -item: Edit Registry - Total Keys=1 - Key=Python.NoConFile - New Value=Python File (no console) -end -item: Edit Registry - Total Keys=1 - Key=Python.NoConFile\shell\open\command - New Value=%MAINDIR%\pythonw.exe "%%1" %%* -end -item: Edit Registry - Total Keys=1 - Key=Python.NoConFile\DefaultIcon - New Value=%MAINDIR%\Py.ico -end -item: Remark -end -item: Edit Registry - Total Keys=1 - Key=Python.CompiledFile - New Value=Compiled Python File -end -item: Edit Registry - Total Keys=1 - Key=Python.CompiledFile\shell\open\command - New Value=%MAINDIR%\python.exe "%%1" %%* -end -item: Edit Registry - Total Keys=1 - Key=Python.CompiledFile\DefaultIcon - New Value=%MAINDIR%\pyc.ico -end -item: Remark -end -item: Remark - Text=File extensions. -end -item: Edit Registry - Total Keys=1 - Key=.py - New Value=Python.File -end -item: Edit Registry - Total Keys=1 - Key=.py - New Value=text/plain - Value Name=Content Type -end -item: Remark -end -item: Edit Registry - Total Keys=1 - Key=.pyw - New Value=Python.NoConFile -end -item: Edit Registry - Total Keys=1 - Key=.pyw - New Value=text/plain - Value Name=Content Type -end -item: Remark -end -item: Edit Registry - Total Keys=1 - Key=.pyc - New Value=Python.CompiledFile -end -item: Edit Registry - Total Keys=1 - Key=.pyo - New Value=Python.CompiledFile -end -item: Else Statement -end -item: Remark - Text=File types. -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.File - New Value=Python File - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.File\shell\open\command - New Value=%MAINDIR%\python.exe "%%1" %%* - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.File\DefaultIcon - New Value=%MAINDIR%\Py.ico - Root=1 -end -item: Remark -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.NoConFile - New Value=Python File (no console) - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.NoConFile\shell\open\command - New Value=%MAINDIR%\pythonw.exe "%%1" %%* - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.NoConFile\DefaultIcon - New Value=%MAINDIR%\Py.ico - Root=1 -end -item: Remark -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.CompiledFile - New Value=Compiled Python File - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.CompiledFile\shell\open\command - New Value=%MAINDIR%\python.exe "%%1" %%* - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.CompiledFile\DefaultIcon - New Value=%MAINDIR%\pyc.ico - Root=1 -end -item: Remark -end -item: Remark - Text=File extensions. -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\.py - New Value=Python.File - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\.py - New Value=text/plain - Value Name=Content Type - Root=1 -end -item: Remark -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\.pyw - New Value=Python.NoConFile - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\.pyw - New Value=text/plain - Value Name=Content Type - Root=1 -end -item: Remark -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\.pyc - New Value=Python.CompiledFile - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\.pyo - New Value=Python.CompiledFile - Root=1 -end -item: End Block -end -item: Remark -end -item: Remark - Text=If we're installing IDLE, also set an Edit context menu action to use IDLE, for .py and .pyw files. -end -item: If/While Statement - Variable=COMPONENTS - Value=B - Flags=00000010 -end -item: If/While Statement - Variable=USE_HKCR - Value=1 -end -item: Edit Registry - Total Keys=1 - Key=Python.NoConFile\shell\Edit with IDLE\command - New Value=%MAINDIR%\pythonw.exe %MAINDIR%\Lib\idlelib\idle.pyw -n -e "%%1" -end -item: Edit Registry - Total Keys=1 - Key=Python.File\shell\Edit with IDLE\command - New Value=%MAINDIR%\pythonw.exe %MAINDIR%\Lib\idlelib\idle.pyw -n -e "%%1" -end -item: Else Statement -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.NoConFile\shell\Edit with IDLE\command - New Value=%MAINDIR%\pythonw.exe %MAINDIR%\Lib\idlelib\idle.pyw -n -e "%%1" - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\CLASSES\Python.File\shell\Edit with IDLE\command - New Value=%MAINDIR%\pythonw.exe %MAINDIR%\Lib\idlelib\idle.pyw -n -e "%%1" - Root=1 -end -item: End Block -end -item: End Block -end -item: End Block -end -item: Remark -end -item: Remark - Text=Register Python paths. -end -item: Remark - Text=Write to HKLM for admin, else HKCU. Keep these blocks otherwise identical! -end -item: If/While Statement - Variable=DOADMIN - Value=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\CurrentVersion - Root=130 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\InstallPath - New Value=%MAINDIR% - Root=2 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\InstallPath\InstallGroup - New Value=%CGROUP_SAVE% - New Value= - Root=2 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\PythonPath - New Value=%MAINDIR%\Lib;%MAINDIR%\DLLs;%MAINDIR%\Lib\lib-tk - New Value= - Root=2 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\Modules - Root=2 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\App Paths\Python.exe - New Value=%MAINDIR%\Python.exe - Root=2 -end -item: Else Statement -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\CurrentVersion - Root=129 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\InstallPath - New Value=%MAINDIR% - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\InstallPath\InstallGroup - New Value=%CGROUP_SAVE% - New Value= - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\PythonPath - New Value=%MAINDIR%\Lib;%MAINDIR%\DLLs;%MAINDIR%\Lib\lib-tk - New Value= - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\Modules - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\App Paths\Python.exe - New Value=%MAINDIR%\Python.exe - Root=1 -end -item: End Block -end -item: End Block -end -item: Remark -end -item: Remark - Text=Registry fiddling for docs. -end -item: Remark - Text=Write to HKLM for admin, else HKCU. Keep these blocks otherwise identical! -end -item: If/While Statement - Variable=COMPONENTS - Value=C - Flags=00000010 -end -item: If/While Statement - Variable=DOADMIN - Value=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\Help\Main Python Documentation - New Value=%MAINDIR%\Doc\index.html - Root=2 -end -item: Else Statement -end -item: Edit Registry - Total Keys=1 - Key=Software\Python\PythonCore\%PY_VERSION%\Help\Main Python Documentation - New Value=%MAINDIR%\Doc\index.html - Root=1 -end -item: End Block -end -item: End Block -end -item: Remark -end -item: Remark - Text=Set the app publisher and URL entries for Win2K add/remove. -end -item: Remark - Text=It doesn't hurt on other systems. -end -item: Remark - Text=As usual, write to HKLM or HKCU depending on Admin privs. -end -item: Remark - Text=CAUTION: If you set this info on the "Windows 2000" page (step 6) of the -end -item: Remark - Text=Installation Expert, it only shows up in the "If" block below. Keep in synch! -end -item: If/While Statement - Variable=DOADMIN - Value=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=http://www.python.org/ - Value Name=HelpLink - Root=2 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=PythonLabs at Zope Corporation - Value Name=Publisher - Root=2 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=http://www.python.org/ - Value Name=URLInfoAbout - Root=2 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%PYVER_STRING% - Value Name=DisplayVersion - Root=2 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%MAINDIR%\py.ico,-0 - Value Name=DisplayIcon - Root=2 -end -item: Else Statement -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=http://www.python.org/ - Value Name=HelpLink - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=PythonLabs at Zope Corporation - Value Name=Publisher - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=http://www.python.org/ - Value Name=URLInfoAbout - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%PYVER_STRING% - Value Name=DisplayVersion - Root=1 -end -item: Edit Registry - Total Keys=1 - Key=Software\Microsoft\Windows\CurrentVersion\Uninstall\%APPTITLE% - New Value=%MAINDIR%\py.ico,-0 - Value Name=DisplayIcon - Root=1 -end -item: End Block -end -item: Remark -end -item: Remark - Text=Populate Start Menu group -end -item: If/While Statement - Variable=TASKS - Value=B - Flags=00000010 -end -item: Remark - Text=Shortcut to installer no matter what. -end -item: Create Shortcut - Source=%MAINDIR%\unwise.exe - Destination=%GROUP%\Uninstall Python.lnk - Working Directory=%MAINDIR% - Key Type=1536 - Flags=00000001 -end -item: Remark -end -item: If/While Statement - Variable=COMPONENTS - Value=A - Flags=00000010 -end -item: Create Shortcut - Source=%MAINDIR%\python.exe - Destination=%GROUP%\Python (command line).lnk - Working Directory=%MAINDIR% - Icon Pathname=%MAINDIR%\pycon.ico - Key Type=1536 - Flags=00000001 -end -item: End Block -end -item: Remark -end -item: If/While Statement - Variable=COMPONENTS - Value=B - Flags=00000010 -end -item: Create Shortcut - Source=%MAINDIR%\pythonw.exe - Destination=%GROUP%\IDLE (Python GUI).lnk - Command Options="%MAINDIR%\Lib\idlelib\idle.pyw" - Working Directory=%MAINDIR% - Key Type=1536 - Flags=00000001 -end -item: Create Shortcut - Source=%MAINDIR%\pythonw.exe - Destination=%GROUP%\Module Docs.lnk - Command Options="%MAINDIR%\Tools\Scripts\pydocgui.pyw" - Working Directory=%MAINDIR% - Key Type=1536 - Flags=00000001 -end -item: End Block -end -item: Remark -end -item: If/While Statement - Variable=COMPONENTS - Value=C - Flags=00000010 -end -item: Create Shortcut - Source=%MAINDIR%\Doc\index.html - Destination=%GROUP%\Python Manuals.lnk - Working Directory=%MAINDIR% - Key Type=1536 - Flags=00000001 -end -item: End Block -end -item: End Block -end -item: Remark -end -item: Remark - Text=I don't think we need this, but have always done it. -end -item: Self-Register OCXs/DLLs - Description=Updating System Configuration, Please Wait... -end -item: Remark -end -remarked item: Remark - Text=Don't enable "Delete in-use files". Here's what happens: -end -remarked item: Remark - Text=Install Python; uninstall Python; install Python again. Reboot the machine. -end -remarked item: Remark - Text=Now UNWISE.EXE is missing. I think this is a Wise bug, but so it goes. -end -remarked item: Add Text to INSTALL.LOG - Text=Delete in-use files: On -end -item: Remark -end -item: Wizard Block - Direction Variable=DIRECTION - Display Variable=DISPLAY - Bitmap Pathname=.\installer.bmp - X Position=9 - Y Position=10 - Filler Color=11173759 - Flags=00000011 -end -item: Custom Dialog Set - Name=Finished - Display Variable=DISPLAY - item: Dialog - Title=%APPTITLE% Installation - Title French=Installation de %APPTITLE% - Title German=Installation von %APPTITLE% - Title Spanish=Instalaci?n de %APPTITLE% - Title Italian=Installazione di %APPTITLE% - Width=339 - Height=280 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=188 234 244 253 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Finish - Text French=&Fin - Text German=&Weiter - Text Spanish=&Terminar - Text Italian=&Fine - end - item: Push Button - Rectangle=264 234 320 253 - Variable=DISABLED - Value=! - Action=3 - Create Flags=01010000000000010000000000000000 - Text=&Cancel - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Static - Rectangle=108 10 323 48 - Create Flags=01010000000000000000000000000000 - Flags=0000000000000001 - Name=Times New Roman - Font Style=-24 0 0 0 700 255 0 0 0 3 2 1 18 - Text=Installation Completed! - Text French=Installation termin?e ! - Text German=Die Installation ist abgeschlossen! - Text Spanish=?Instalaci?n terminada! - Text Italian=Installazione completata! - end - item: Static - Rectangle=108 44 320 82 - Create Flags=01010000000000000000000000000000 - Text=%APPTITLE% has been successfully installed. - Text= - Text=Press the Finish button to exit this installation. - Text French=%APPTITLE% est maintenant install?. - Text French= - Text French=Cliquez sur le bouton Fin pour quitter l'installation. - Text German=%APPTITLE% wurde erfolgreich installiert. - Text German= - Text German=Klicken Sie auf "Weiter", um die Installation zu beenden. - Text Spanish=%APPTITLE% se ha instalado con ?xito. - Text Spanish= - Text Spanish=Presione el bot?n Terminar para salir de esta instalaci?n. - Text Italian=L'installazione %APPTITLE% ? stata portata a termine con successo. - Text Italian= - Text Italian=Premere il pulsante Fine per uscire dall'installazione. - end - item: Static - Rectangle=10 225 320 226 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=106 105 312 210 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000000000 - Text=Special Windows thanks to: - Text= - Text=Wise Solutions, for the use of InstallMaster 8.1. - Text= http://www.wisesolutions.com/ - Text= - Text= - Text=LettError, Erik van Blokland, for the Python for Windows graphic. - Text= http://www.letterror.com/ - Text= - Text= - Text=Mark Hammond, without whose years of freely shared Windows expertise, Python for Windows would still be Python for DOS. - end - item: Static - Rectangle=106 95 312 96 - Action=3 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000001001 - end - end -end -item: End Block -end -item: New Event - Name=Cancel -end -item: Remark - Text=This include script supports a rollback to preinstallation state if the user chooses to cancel before the installation is complete. -end -item: Include Script - Pathname=%_WISE_%\INCLUDE\rollback.wse -end Deleted: /python/trunk/PCbuild8/pythoncore.vcproj ============================================================================== --- /python/trunk/PCbuild8/pythoncore.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,1946 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/pythoncore/getbuildinfo.vsprops ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/pythoncore/getbuildinfo.vsprops Mon Apr 30 17:17:46 2007 @@ -0,0 +1,12 @@ + + + + Added: python/trunk/PCbuild8/pythoncore/pythoncore.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/pythoncore/pythoncore.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,1876 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/pythonw.vcproj ============================================================================== --- /python/trunk/PCbuild8/pythonw.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,383 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/pythonw/pythonw.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/pythonw/pythonw.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,648 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modified: python/trunk/PCbuild8/readme.txt ============================================================================== --- python/trunk/PCbuild8/readme.txt (original) +++ python/trunk/PCbuild8/readme.txt Mon Apr 30 17:17:46 2007 @@ -2,44 +2,66 @@ ------------------------------------- This directory is used to build Python for Win32 platforms, e.g. Windows 95, 98 and NT. It requires Microsoft Visual C++ 8.0 -(a.k.a. Visual Studio 2005). +(a.k.a. Visual Studio 2005). There are two Platforms defined, Win32 +and x64. (For other Windows platforms and compilers, see ../PC/readme.txt.) All you need to do is open the workspace "pcbuild.sln" in MSVC++, select the Debug or Release setting (using "Solution Configuration" from -the "Standard" toolbar"), and build the projects. +the "Standard" toolbar"), and build the solution. -The proper order to build subprojects: +A .bat file, build.bat, is provided to simplify command line builds. -1) pythoncore (this builds the main Python DLL and library files, - python26.{dll, lib} in Release mode) - NOTE: in previous releases, this subproject was - named after the release number, e.g. python20. - -2) python (this builds the main Python executable, - python.exe in Release mode) - -3) the other subprojects, as desired or needed (note: you probably don't - want to build most of the other subprojects, unless you're building an - entire Python distribution from scratch, or specifically making changes - to the subsystems they implement, or are running a Python core buildbot - test slave; see SUBPROJECTS below) +Some of the subprojects rely on external libraries and won't build +unless you have them installed. -Binary files go into PCBuild8\Win32 or \x64 directories and don't -interfere with each other. +Binary files go into PCBuild8\$(PlatformName)($ConfigurationName), +which will be something like Win32Debug, Win32Release, x64Release, etc. When using the Debug setting, the output files have a _d added to their name: python26_d.dll, python_d.exe, parser_d.pyd, and so on. -There are two special configurations for the pythoncore project and -the solution. These are PGIRelease and PGORelease. They are for -createing profile-guided optimized versions of python.dll. -The former creates the instrumented binaries, and the latter -runs python.exe with the instrumented python.dll on the performance -testsuite, and creates a new, optimized, python.dll in -PCBuild8\Win32\PGORelease, or in the x64 folder. Note that although -we can cross-compile x64 binaries on a 32 bit machine, we cannot -create the PGO binaries, since they require actually running the code. +PROFILER GUIDED OPTIMIZATION +---------------------------- +There are two special solution configurations for Profiler Guided +Optimization. Careful use of this has been shown to yield more than +10% extra speed. +1) Build the PGInstrument solution configuration. This will yield +binaries in the win32PGO or x64PGO folders. (You may want do start +by erasing any .pgc files there, present from earlier runs.) +2) Instrument the binaries. Do this by for example running the test +suite: win32PGO\python.exe ..\lib\test\regrtest.py. This will excercise +python thoroughly. +3) Build the PGUpdate solution configuration (You may need to ask it +to rebuild.) This will incorporate the information gathered in step 2 +and produce new binaries in the same win32PGO or x64pPGO folders. +4) (optional) You can continue to build the PGUpdate configuration as +you work on python. It will continue to use the data from step 2, even +if you add or modify files as part of your work. Thus, it makes sense to +run steps 1 and 2 maybe once a week, and then use step 3) for all regular +work. + +A .bat file, build_pgo.bat is included to automate this process + +You can convince yourself of the benefits of the PGO by comparing the +results of the python testsuite with the regular Release build. + + +C RUNTIME +--------- +Visual Studio 2005 uses version 8 of the C runtime. The executables are +linked to a CRT "side by side" assembly which must be present on the target +machine. This is avalible under the VC/Redist folder of your visual studio +distribution. Note that ServicePack1 of Visual Studio 2005 has a different +version than the original. On XP and later operating systems that support +side-by-side assemblies it is not enough to have the msvcrt80.dll present, +it has to be there as a whole assembly, that is, a folder with the .dll +and a .manifest. Also, a check is made for the correct version. +Therefore, one should distribute this assembly with the dlls, and keep +it in the same directory. For compatibility with older systems, one should +also set the PATH to this directory so that the dll can be found. +For more info, see the Readme in the VC/Redist folder. + SUBPROJECTS ----------- @@ -267,164 +289,22 @@ build_ssl.py/MSVC isn't clever enough to clean OpenSSL - you must do this by hand. -Building for Itanium --------------------- - -The project files support a ReleaseItanium configuration which creates -Win64/Itanium binaries. For this to work, you need to install the Platform -SDK, in particular the 64-bit support. This includes an Itanium compiler -(future releases of the SDK likely include an AMD64 compiler as well). -In addition, you need the Visual Studio plugin for external C compilers, -from http://sf.net/projects/vsextcomp. The plugin will wrap cl.exe, to -locate the proper target compiler, and convert compiler options -accordingly. The project files require atleast version 0.8. Building for AMD64 ------------------ -The build process for the ReleaseAMD64 configuration is very similar -to the Itanium configuration; make sure you use the latest version of -vsextcomp. - -Building Python Using the free MS Toolkit Compiler --------------------------------------------------- - -The build process for Visual C++ can be used almost unchanged with the free MS -Toolkit Compiler. This provides a way of building Python using freely -available software. - -Requirements - - To build Python, the following tools are required: - - * The Visual C++ Toolkit Compiler - from http://msdn.microsoft.com/visualc/vctoolkit2003/ - * A recent Platform SDK - from http://www.microsoft.com/downloads/details.aspx?FamilyID=484269e2-3b89-47e3-8eb7-1f2be6d7123a - * The .NET 1.1 SDK - from http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d - - [Does anyone have better URLs for the last 2 of these?] - - The toolkit compiler is needed as it is an optimising compiler (the - compiler supplied with the .NET SDK is a non-optimising version). The - platform SDK is needed to provide the Windows header files and libraries - (the Windows 2003 Server SP1 edition, typical install, is known to work - - other configurations or versions are probably fine as well). The .NET 1.1 - SDK is needed because it contains a version of msvcrt.dll which links to - the msvcr71.dll CRT. Note that the .NET 2.0 SDK is NOT acceptable, as it - references msvcr80.dll. - - All of the above items should be installed as normal. - - If you intend to build the openssl (needed for the _ssl extension) you - will need the C runtime sources installed as part of the platform SDK. - - In addition, you will need Nant, available from - http://nant.sourceforge.net. The 0.85 release candidate 3 version is known - to work. This is the latest released version at the time of writing. Later - "nightly build" versions are known NOT to work - it is not clear at - present whether future released versions will work. - -Setting up the environment - - Start a platform SDK "build environment window" from the start menu. The - "Windows XP 32-bit retail" version is known to work. - - Add the following directories to your PATH: - * The toolkit compiler directory - * The SDK "Win64" binaries directory - * The Nant directory - Add to your INCLUDE environment variable: - * The toolkit compiler INCLUDE directory - Add to your LIB environment variable: - * The toolkit compiler LIB directory - * The .NET SDK Visual Studio 2003 VC7\lib directory - - The following commands should set things up as you need them: - - rem Set these values according to where you installed the software - set TOOLKIT=C:\Program Files\Microsoft Visual C++ Toolkit 2003 - set SDK=C:\Program Files\Microsoft Platform SDK - set NET=C:\Program Files\Microsoft Visual Studio .NET 2003 - set NANT=C:\Utils\Nant - - set PATH=%TOOLKIT%\bin;%PATH%;%SDK%\Bin\win64;%NANT%\bin - set INCLUDE=%TOOLKIT%\include;%INCLUDE% - set LIB=%TOOLKIT%\lib;%NET%\VC7\lib;%LIB% - - The "win64" directory from the SDK is added to supply executables such as - "cvtres" and "lib", which are not available elsewhere. The versions in the - "win64" directory are 32-bit programs, so they are fine to use here. - - That's it. To build Python (the core only, no binary extensions which - depend on external libraries) you just need to issue the command - - nant -buildfile:python.build all - - from within the PCBuild directory. - -Extension modules - - To build those extension modules which require external libraries - (_tkinter, bz2, _bsddb, _sqlite3, _ssl) you can follow the instructions - for the Visual Studio build above, with a few minor modifications. These - instructions have only been tested using the sources in the Python - subversion repository - building from original sources should work, but - has not been tested. - - For each extension module you wish to build, you should remove the - associated include line from the excludeprojects section of pc.build. - - The changes required are: - - _tkinter - The tix makefile (tix-8.4.0\win\makefile.vc) must be modified to - remove references to TOOLS32. The relevant lines should be changed to - read: - cc32 = cl.exe - link32 = link.exe - include32 = - The remainder of the build instructions will work as given. - - bz2 - No changes are needed - - _bsddb - The file db.build should be copied from the Python PCBuild directory - to the directory db-4.4.20\build_win32. - - The file db_static.vcproj in db-4.4.20\build_win32 should be edited to - remove the string "$(SolutionDir)" - this occurs in 2 places, only - relevant for 64-bit builds. (The edit is required as otherwise, nant - wants to read the solution file, which is not in a suitable form). - - The bsddb library can then be build with the command - nant -buildfile:db.build all - run from the db-4.4.20\build_win32 directory. - - _sqlite3 - No changes are needed. However, in order for the tests to succeed, a - copy of sqlite3.dll must be downloaded, and placed alongside - python.exe. - - _ssl - The documented build process works as written. However, it needs a - copy of the file setargv.obj, which is not supplied in the platform - SDK. However, the sources are available (in the crt source code). To - build setargv.obj, proceed as follows: - - Copy setargv.c, cruntime.h and internal.h from %SDK%\src\crt to a - temporary directory. - Compile using "cl /c /I. /MD /D_CRTBLD setargv.c" - Copy the resulting setargv.obj to somewhere on your LIB environment - (%SDK%\lib is a reasonable place). +Select x64 as the destination platform. - With setargv.obj in place, the standard build process should work - fine. YOUR OWN EXTENSION DLLs ----------------------- If you want to create your own extension module DLL, there's an example with easy-to-follow instructions in ../PC/example/; read the file readme.txt there first. +Also, you can simply use Visual Studio to "Add new project to solution". +Elect to create a win32 project, .dll, empty project. +This will create a subdirectory with a .vcproj file in it. Now, You can +simply copy most of another .vcproj, like _test_capi/_test_capi.vcproj over +(you can't just copy and rename it, since the target will have a unique GUID.) +At some point we want to be able to provide a template for creating a +project. Modified: python/trunk/PCbuild8/rmpyc.py ============================================================================== --- python/trunk/PCbuild8/rmpyc.py (original) +++ python/trunk/PCbuild8/rmpyc.py Mon Apr 30 17:17:46 2007 @@ -1,4 +1,5 @@ # Remove all the .pyc and .pyo files under ../Lib. +import sys def deltree(root): @@ -21,5 +22,9 @@ return npyc, npyo -npyc, npyo = deltree("../Lib") +path = "../Lib" +if len(sys.argv) > 1: + path = sys.argv[1] + +npyc, npyo = deltree(path) print npyc, ".pyc deleted,", npyo, ".pyo deleted" Modified: python/trunk/PCbuild8/rt.bat ============================================================================== --- python/trunk/PCbuild8/rt.bat (original) +++ python/trunk/PCbuild8/rt.bat Mon Apr 30 17:17:46 2007 @@ -2,6 +2,8 @@ rem Run Tests. Run the regression test suite. rem Usage: rt [-d] [-O] [-q] regrtest_args rem -d Run Debug build (python_d.exe). Else release build. +rem -pgo Run PGO build, e.g. for instrumentation +rem -x64 Run the x64 version, otherwise win32 rem -O Run python.exe or python_d.exe (see -d) with -O. rem -q "quick" -- normally the tests are run twice, the first time rem after deleting all the .py[co] files reachable from Lib/. @@ -24,16 +26,21 @@ setlocal -set exe=python +set platf=win32 +set exe=python.exe set qmode= set dashO= +set conf=Release PATH %PATH%;..\..\tcltk\bin :CheckOpts if "%1"=="-O" (set dashO=-O) & shift & goto CheckOpts if "%1"=="-q" (set qmode=yes) & shift & goto CheckOpts -if "%1"=="-d" (set exe=python_d) & shift & goto CheckOpts +if "%1"=="-d" (set exe=python_d.exe) & (set conf=Debug) & shift & goto CheckOpts +if "%1"=="-x64" (set platf=x64) & shift & goto CheckOpts +if "%1"=="-pgo" (set conf=PGO) & shift & goto CheckOpts +set exe=%platf%%conf%\%exe% set cmd=%exe% %dashO% -E -tt ../lib/test/regrtest.py %1 %2 %3 %4 %5 %6 %7 %8 %9 if defined qmode goto Qmode Deleted: /python/trunk/PCbuild8/select.vcproj ============================================================================== --- /python/trunk/PCbuild8/select.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,379 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/select/select.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/select/select.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,644 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/unicodedata.vcproj ============================================================================== --- /python/trunk/PCbuild8/unicodedata.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,371 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/unicodedata/unicodedata.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/unicodedata/unicodedata.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,636 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deleted: /python/trunk/PCbuild8/w9xpopen.vcproj ============================================================================== --- /python/trunk/PCbuild8/w9xpopen.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,353 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Deleted: /python/trunk/PCbuild8/winsound.vcproj ============================================================================== --- /python/trunk/PCbuild8/winsound.vcproj Mon Apr 30 17:17:46 2007 +++ (empty file) @@ -1,375 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Added: python/trunk/PCbuild8/winsound/winsound.vcproj ============================================================================== --- (empty file) +++ python/trunk/PCbuild8/winsound/winsound.vcproj Mon Apr 30 17:17:46 2007 @@ -0,0 +1,644 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From python-checkins at python.org Mon Apr 30 17:44:23 2007 From: python-checkins at python.org (thomas.heller) Date: Mon, 30 Apr 2007 17:44:23 +0200 (CEST) Subject: [Python-checkins] r55025 - python/trunk/Modules/_ctypes/callproc.c python/trunk/Modules/_ctypes/cfield.c python/trunk/Modules/_ctypes/stgdict.c Message-ID: <20070430154423.DDEA71E4012@bag.python.org> Author: thomas.heller Date: Mon Apr 30 17:44:17 2007 New Revision: 55025 Modified: python/trunk/Modules/_ctypes/callproc.c python/trunk/Modules/_ctypes/cfield.c python/trunk/Modules/_ctypes/stgdict.c Log: Make sure to call PyErr_NoMemory() in several places where PyMem_Malloc() could potentially fail. Will backport to the release25-maint branch. Modified: python/trunk/Modules/_ctypes/callproc.c ============================================================================== --- python/trunk/Modules/_ctypes/callproc.c (original) +++ python/trunk/Modules/_ctypes/callproc.c Mon Apr 30 17:44:17 2007 @@ -539,8 +539,10 @@ size += 1; /* terminating NUL */ size *= sizeof(wchar_t); pa->value.p = PyMem_Malloc(size); - if (!pa->value.p) + if (!pa->value.p) { + PyErr_NoMemory(); return -1; + } memset(pa->value.p, 0, size); pa->keep = PyCObject_FromVoidPtr(pa->value.p, PyMem_Free); if (!pa->keep) { Modified: python/trunk/Modules/_ctypes/cfield.c ============================================================================== --- python/trunk/Modules/_ctypes/cfield.c (original) +++ python/trunk/Modules/_ctypes/cfield.c Mon Apr 30 17:44:17 2007 @@ -1426,7 +1426,7 @@ size *= sizeof(wchar_t); buffer = (wchar_t *)PyMem_Malloc(size); if (!buffer) - return NULL; + return PyErr_NoMemory(); memset(buffer, 0, size); keep = PyCObject_FromVoidPtr(buffer, PyMem_Free); if (!keep) { Modified: python/trunk/Modules/_ctypes/stgdict.c ============================================================================== --- python/trunk/Modules/_ctypes/stgdict.c (original) +++ python/trunk/Modules/_ctypes/stgdict.c Mon Apr 30 17:44:17 2007 @@ -72,8 +72,10 @@ return 0; size = sizeof(ffi_type *) * (src->length + 1); dst->ffi_type_pointer.elements = PyMem_Malloc(size); - if (dst->ffi_type_pointer.elements == NULL) + if (dst->ffi_type_pointer.elements == NULL) { + PyErr_NoMemory(); return -1; + } memcpy(dst->ffi_type_pointer.elements, src->ffi_type_pointer.elements, size); @@ -359,6 +361,10 @@ total_align = align ? align : 1; stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT; stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (basedict->length + len + 1)); + if (stgdict->ffi_type_pointer.elements == NULL) { + PyErr_NoMemory(); + return -1; + } memset(stgdict->ffi_type_pointer.elements, 0, sizeof(ffi_type *) * (basedict->length + len + 1)); memcpy(stgdict->ffi_type_pointer.elements, @@ -373,6 +379,10 @@ total_align = 1; stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT; stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (len + 1)); + if (stgdict->ffi_type_pointer.elements == NULL) { + PyErr_NoMemory(); + return -1; + } memset(stgdict->ffi_type_pointer.elements, 0, sizeof(ffi_type *) * (len + 1)); ffi_ofs = 0; From python-checkins at python.org Mon Apr 30 17:58:52 2007 From: python-checkins at python.org (thomas.heller) Date: Mon, 30 Apr 2007 17:58:52 +0200 (CEST) Subject: [Python-checkins] r55026 - python/branches/release25-maint/Modules/_ctypes python/branches/release25-maint/Modules/_ctypes/callproc.c python/branches/release25-maint/Modules/_ctypes/cfield.c python/branches/release25-maint/Modules/_ctypes/stgdict.c Message-ID: <20070430155852.DECF01E400A@bag.python.org> Author: thomas.heller Date: Mon Apr 30 17:58:51 2007 New Revision: 55026 Modified: python/branches/release25-maint/Modules/_ctypes/ (props changed) python/branches/release25-maint/Modules/_ctypes/callproc.c python/branches/release25-maint/Modules/_ctypes/cfield.c python/branches/release25-maint/Modules/_ctypes/stgdict.c Log: Merged revisions 55025 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk/Modules/_ctypes ........ r55025 | thomas.heller | 2007-04-30 17:44:17 +0200 (Mo, 30 Apr 2007) | 4 lines Make sure to call PyErr_NoMemory() in several places where PyMem_Malloc() could potentially fail. Will backport to the release25-maint branch. ........ Modified: python/branches/release25-maint/Modules/_ctypes/callproc.c ============================================================================== --- python/branches/release25-maint/Modules/_ctypes/callproc.c (original) +++ python/branches/release25-maint/Modules/_ctypes/callproc.c Mon Apr 30 17:58:51 2007 @@ -539,8 +539,10 @@ size += 1; /* terminating NUL */ size *= sizeof(wchar_t); pa->value.p = PyMem_Malloc(size); - if (!pa->value.p) + if (!pa->value.p) { + PyErr_NoMemory(); return -1; + } memset(pa->value.p, 0, size); pa->keep = PyCObject_FromVoidPtr(pa->value.p, PyMem_Free); if (!pa->keep) { Modified: python/branches/release25-maint/Modules/_ctypes/cfield.c ============================================================================== --- python/branches/release25-maint/Modules/_ctypes/cfield.c (original) +++ python/branches/release25-maint/Modules/_ctypes/cfield.c Mon Apr 30 17:58:51 2007 @@ -1389,7 +1389,7 @@ size *= sizeof(wchar_t); buffer = (wchar_t *)PyMem_Malloc(size); if (!buffer) - return NULL; + return PyErr_NoMemory(); memset(buffer, 0, size); keep = PyCObject_FromVoidPtr(buffer, PyMem_Free); if (!keep) { Modified: python/branches/release25-maint/Modules/_ctypes/stgdict.c ============================================================================== --- python/branches/release25-maint/Modules/_ctypes/stgdict.c (original) +++ python/branches/release25-maint/Modules/_ctypes/stgdict.c Mon Apr 30 17:58:51 2007 @@ -72,8 +72,10 @@ return 0; size = sizeof(ffi_type *) * (src->length + 1); dst->ffi_type_pointer.elements = PyMem_Malloc(size); - if (dst->ffi_type_pointer.elements == NULL) + if (dst->ffi_type_pointer.elements == NULL) { + PyErr_NoMemory(); return -1; + } memcpy(dst->ffi_type_pointer.elements, src->ffi_type_pointer.elements, size); @@ -359,6 +361,10 @@ total_align = align ? align : 1; stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT; stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (basedict->length + len + 1)); + if (stgdict->ffi_type_pointer.elements == NULL) { + PyErr_NoMemory(); + return -1; + } memset(stgdict->ffi_type_pointer.elements, 0, sizeof(ffi_type *) * (basedict->length + len + 1)); memcpy(stgdict->ffi_type_pointer.elements, @@ -373,6 +379,10 @@ total_align = 1; stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT; stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (len + 1)); + if (stgdict->ffi_type_pointer.elements == NULL) { + PyErr_NoMemory(); + return -1; + } memset(stgdict->ffi_type_pointer.elements, 0, sizeof(ffi_type *) * (len + 1)); ffi_ofs = 0; From buildbot at python.org Mon Apr 30 18:00:39 2007 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Apr 2007 16:00:39 +0000 Subject: [Python-checkins] buildbot warnings in x86 mvlgcc trunk Message-ID: <20070430160039.568F41E400A@bag.python.org> The Buildbot has detected a new failure of x86 mvlgcc trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%2520mvlgcc%2520trunk/builds/495 Buildbot URL: http://www.python.org/dev/buildbot/all/ Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: thomas.heller Build had warnings: warnings test Excerpt from the test logfile: Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/threading.py", line 460, in __bootstrap self.run() File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/threading.py", line 440, in run self.__target(*self.__args, **self.__kwargs) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/bsddb/test/test_thread.py", line 281, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home2/buildbot/slave/trunk.loewis-linux/build/Lib/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') sincerely, -The Buildbot From python-checkins at python.org Mon Apr 30 18:05:01 2007 From: python-checkins at python.org (thomas.heller) Date: Mon, 30 Apr 2007 18:05:01 +0200 (CEST) Subject: [Python-checkins] r55027 - python/trunk/Modules/_ctypes/cfield.c Message-ID: <20070430160501.B32CE1E400C@bag.python.org> Author: thomas.heller Date: Mon Apr 30 18:04:57 2007 New Revision: 55027 Modified: python/trunk/Modules/_ctypes/cfield.c Log: When accessing the .value attribute of a c_wchar_p instance, and the instance does not point to a valid wchar_t zero-terminated string, raise a ValueError. c_char_p does this already. The ValueError message now contains the correct pointer address. Will backport to release25-maint. Modified: python/trunk/Modules/_ctypes/cfield.c ============================================================================== --- python/trunk/Modules/_ctypes/cfield.c (original) +++ python/trunk/Modules/_ctypes/cfield.c Mon Apr 30 18:04:57 2007 @@ -1366,7 +1366,7 @@ if (IsBadStringPtrA(*(char **)ptr, -1)) { PyErr_Format(PyExc_ValueError, "invalid string pointer %p", - ptr); + *(char **)ptr); return NULL; } #endif @@ -1451,9 +1451,17 @@ { wchar_t *p; p = *(wchar_t **)ptr; - if (p) + if (p) { +#if defined(MS_WIN32) && !defined(_WIN32_WCE) + if (IsBadStringPtrW(*(wchar_t **)ptr, -1)) { + PyErr_Format(PyExc_ValueError, + "invalid string pointer %p", + *(wchar_t **)ptr); + return NULL; + } +#endif return PyUnicode_FromWideChar(p, wcslen(p)); - else { + } else { Py_INCREF(Py_None); return Py_None; }